11. Design examples¶

11.1. Introduction¶

In previous chapters, some simple designs were introduces e.g. mod-m counter and flip-flops etc. to introduce the VHDL programming. In this chapter various examples are added, which can be used to implement or emulate a system on the FPGA board.

All the design files are provided inside the 'VHDLCodes' folder inside the main project directory; which can be used to implement the design using some other software as well. Each section shows the list of VHDL-files require to implement the design in that section. Lastly, all designs are tested using Modelsim and on Altera-DE2 FPGA board. Set a desired design as 'top-level entity' to implement or simulate it.

11.2. Random number generator¶

In this section, random number generator is implemented using linear feedback shift register. VHDL files required for this example are listed below,

  • rand_num_generator.vhd
  • rand_num_generator_visualTest.vhd
  • clockTick.vhd
  • modMCounter.vhd

Note that, 'clockTick.vhd' and 'modMCounter.vhd' are discussed in Chapter 8.

11.2.1. Linear feedback shift register (LFSR)¶

Long LFSR can be used as 'pseudo-random number generator'. These random numbers are generated based on initial values to LFSR. The sequences of random number can be predicted if the initial value is known. However, if LFSR is quite long (i.e. large number of initial values are possible), then the generated numbers can be considered as random numbers for practical purposes.

LFSR polynomial are written as \({{\mathbf{x}}^{\mathbf{3}}}{\mathbf{ + }}{{\mathbf{x}}^{\mathbf{2}}}{\mathbf{ + 1}}\)}, which indicates that the feedback is provided through output of 'xor' gate whose inputs are connected to positions 3, 2 and 0 of LFSR. Some of the polynomials are listed in Table Table 11.1.

Table 11.1 Feedback polynomials
Number of bits Feedback polynomial
3 \({x^3} + {x^2} + 1\)
4 \({x^4} + {x^3} + 1\)
5 \({x^5} + {x^3} + 1\)
6 \({x^6} + {x^5} + 1\)
7 \({x^7} + {x^6} + 1\)
9 \({x^9} + {x^5} + 1\)
10 \({x^{10}} + {x^7} + 1\)
11 \({x^{11}} + {x^9} + 1\)
15 \({x^{15}} + {x^{14}} + 1\)
17 \({x^{17}} + {x^{14}} + 1\)
18 \({x^{18}} + {x^{11}} + 1\)

Random numbers are generated using LFSR in Listing 11.1. The code implements the design for 3 bit LFSR, which can be modified for LFSR with higher number of bits as shown below,

Explanation Listing 11.1

The listing is currently set according to 3 bit LFSR i.e. N = 3 in Line 16. 'q' is the output of LFSR, which is random in nature. Lines 29-32 sets the initial value for LFSR to 1 during reset operations. Note that, LFSR can not have '0' as initial values. Feedback polynomial is implemented at Line 41. Line 52 shifts the last N bits (i.e. N to 1) to the right by 1 bit and the $N^{th}$ bit is feed with 'feedback_value' and stored in 'r_next' signal. In next clock cycle, value of r_next is assigned to r_reg through Line 34. Lastly, the value r_reg is avalaible to output port from Line 53.

Simulation results are shown in Fig. 11.1. Here, we can see that total 7 different numbers are generated by LFSR, which can be seen between two cursors in the figure. Further, q values are represented in 'hexadecimal format' which are same as r_reg values in 'binary format'.

Note that, in Fig. 11.1, the generated sequence contains '8, C, 6, B, 5, 2 and 1'; and if we initialize the system with any of these values, outputs will contain same set of numbers again. But, if we initialize the system with '3' (which is not the set), then the generate sequences will be entirely different.

../_images/rand_num_generator.jpg

Fig. 11.1 Random number generation with N = 3

To modify the feedback polynomial, first insert the correct number of bits (i.e. N) in Line 16. Next, modify the feedback_value at line 41, according to new value of 'N'.

Note that maximum-length for a polynomial is defined as $2^N-1$, but not all the polynomials generate maximum length; e.g. N = 5 generates total 28 sequences (not 31) before repetition as shown in Fig. 11.2.

Note

Distributions using LFSR:

  • Even number polynomial should be used for generating the 'Uniformly distributed numbers', as it does not miss any number from the sequences.
  • Then, the uniformly distributed numbers can be used to generate the 'Gaussian distribution' using 'center limit theorem'.

../_images/rand_num_generatorN5.jpg

Fig. 11.2 Total sequences are 28 (not 31) for N = 5

Listing 11.1 Random number generation with LFSR

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
                                                                -- rand_num_generator.vhd                                -- created by   :   Meher Krishna Patel                                -- date                 :   22-Dec-16                                -- Feedback polynomial : x^3 + x^2 + 1                                                                -- maximum length : 2^3 - 1 = 7                                -- if generic value is changed,                                -- then choose the correct Feedback polynomial i.e. change 'feedback_value' pattern                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                entity                                rand_num_generator                                is                                generic                                (                                N                                :                                integer                                :=                                3                                );                                port                                (                                clk                                ,                                reset                                :                                in                                std_logic                                ;                                q                                :                                out                                std_logic_vector                                (                                N                                downto                                0                                )                                -- output of LFSR i.e. random number                                );                                end                                rand_num_generator                                ;                                architecture                                arch                                of                                rand_num_generator                                is                                signal                                r_reg                                ,                                r_next                                :                                std_logic_vector                                (                                N                                downto                                0                                );                                signal                                feedback_value                                :                                std_logic                                ;                                -- based on feedback polynomial                                begin                                process                                (                                clk                                ,                                reset                                )                                begin                                if                                (                                reset                                =                                '1'                                )                                then                                -- set initial value to '1'.                                                                r_reg                                (                                0                                )                                <=                                '1'                                ;                                -- 0th bit = 1                                r_reg                                (                                N                                downto                                1                                )                                <=                                (                                others                                =>                                '0'                                );                                -- other bits are 0                                                                elsif                                (                                clk                                'event                                and                                clk                                =                                '1'                                )                                then                                r_reg                                <=                                r_next                                ;                                -- otherwise save the next state                                end                                if                                ;                                end                                process                                ;                                -- N = 3                                -- Feedback polynomial : x^3 + x^2 + 1                                                                -- total sequences (maximum) : 2^3 - 1 = 7                                feedback_value                                <=                                r_reg                                (                                3                                )                                xor                                r_reg                                (                                2                                )                                xor                                r_reg                                (                                0                                );                                -- N = 4                                -- feedback_value <= r_reg(4) xor r_reg(3) xor r_reg(0);                                -- N = 5, maximum length = 28 (not 31)                                -- feedback_value <= r_reg(5) xor r_reg(3) xor r_reg(0);                                -- N = 9                                                                -- feedback_value <= r_reg(9) xor r_reg(5) xor r_reg(0);                                r_next                                <=                                feedback_value                                &                                r_reg                                (                                N                                downto                                1                                );                                q                                <=                                r_reg                                ;                                end                                arch                                ;                              

11.2.2. Visual test¶

Listing 11.2 can be used to test the Listing 11.1 on the FPGA board. Here, 1 second clock pulse is used to visualize the output patterns. Please read Chapter 8 for better understanding of the listing. Note that, N = 3 is set in Line 13 according to Listing 11.1.

For displaying outputs on FPGA board, set reset to 1 and then to 0. Then LEDs will blink to display the generated bit patterns by LFSR; which are shown in Fig. 11.1.

Listing 11.2 Visual test : Random number generation with LFSR

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
                                                                -- rand_num_generator_visualTest.vhd                                -- created by   :   Meher Krishna Patel                                -- date                 :   22-Dec-16                                -- if generic value is changed e.g. N = 5                                -- then go to rand_num_generator for further modification                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                entity                                rand_num_generator_visualTest                                is                                generic                                (                                N                                :                                integer                                :=                                3                                );                                port                                (                                CLOCK_50                                ,                                reset                                :                                in                                std_logic                                ;                                LEDR                                :                                out                                std_logic_vector                                (                                N                                downto                                0                                )                                );                                end                                rand_num_generator_visualTest                                ;                                architecture                                arch                                of                                rand_num_generator_visualTest                                is                                signal                                clk_Pulse1s                                :                                std_logic                                ;                                begin                                -- clock 1 s                                clock_1s                                :                                entity                                work                                .                                clockTick                                generic                                map                                (                                M                                =>                                50000000                                ,                                N                                =>                                26                                )                                port                                map                                (                                clk                                =>                                CLOCK_50                                ,                                reset                                =>                                reset                                ,                                clkPulse                                =>                                clk_Pulse1s                                );                                -- rand_num_generator testing with 1 sec clock pulse                                rand_num_generator_1s                                :                                entity                                work                                .                                rand_num_generator                                port                                map                                (                                clk                                =>                                clk_Pulse1s                                ,                                reset                                =>                                reset                                ,                                q                                =>                                LEDR                                );                                end                                arch                                ;                              

11.3. Shift register¶

Shift register are the registers which are used to shift the stored bit in one or both directions. In this section, shift register is implemented which can be used for shifting data in both direction. Further it can be used as parallel to serial converter or serial to parallel converter. VHDL files required for this example are listed below,

  • shift_register.vhd
  • shift_register_visualTest.vhd
  • clockTick.vhd
  • modMCounter.vhd

Note that, 'clockTick.vhd' and 'modMCounter.vhd' are discussed in Chapter 8.

11.3.1. Bidirectional shift register¶

Listing 11.3 implements the bidirectional shift register which is explained below,

Explanation Listing 11.3

In the listing, the 'ctrl' port is used for 'shifting', 'loading' and 'reading' data operation. Lines 32-39 clear the shift register during reset operation, otherwise go to the next state.

Lines 41-53 performs various operations based on 'ctrl' values. Note that, to perform right shift (Line 47), data is continuously provided from last port i.e. (data(N-1)); whereas for left shift (Line 49) data is provided from first port i.e. (data(0)).

Next, ctrl=''00'' is provided for reading the data. It can be used for serial to parallel conversion i.e. when all the bits are shifted and register is full; then set ctrl to ''00'' and read the data, after that set ctrl to ''01'' or ''10'' for getting next set of bits.

Similarly, for parallel to serial converter, first load the data using ctrl=''11''; and then perform the shift operation until all the bits are read and then again load the data. Note that, in this case, last bit propagates (i.e. data(N-1) for right shift or data(0) for left shift) during shifting; which is actually designed for serial to parallel converter. But this will affect the working of parallel to serial converter, as we will set ctrl to ''11'', when all the data is shifted, therefore all the register which were filled by values from last port, will be overwritten by the new parallel data.

Lastly, data is available on the output port 'q_reg' from Line 55. For, parallel to serial converter, use ony one pin of 'q_reg' i.e. q_reg(0) for right shift or q(N-1) for left shift; whereas for serial to parallel conversion, complete 'q_reg' should be read.

Fig. 11.3 shows the shifting operation performed by the listing. Here first data ( i.e. 00110000) is loaded with ctrl=''11''. Then shifted to right after first cursor and later to the left i.e. after second cursor.

../_images/shift_register.jpg

Fig. 11.3 Right and left shifting operations

Listing 11.3 Bidirectional shift register

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
                                                                -- shift_register.vhd                                -- created by   :   Meher Krishna Patel                                -- date                 :   22-Dec-16                                -- Functionality:                                -- load data and shift it data to left and right                                -- parallel to serial conversion (i.e. first load, then shift)                                -- serial to parallel conversion (i.e. first shift, then read)                                -- inputs:                                -- ctrl : to load-data and shift operations (right and left shift)                                -- data : it is the data to be shifted                                -- q_reg : store the outputs                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                entity                                shift_register                                is                                generic                                (                                N                                :                                integer                                :=                                8                                );                                port                                (                                clk                                ,                                reset                                :                                in                                std_logic                                ;                                ctrl                                :                                in                                std_logic_vector                                (                                1                                downto                                0                                );                                data                                :                                in                                std_logic_vector                                (                                N                                -                                1                                downto                                0                                );                                q_reg                                :                                out                                std_logic_vector                                (                                N                                -                                1                                downto                                0                                )                                );                                end                                shift_register                                ;                                architecture                                arch                                of                                shift_register                                is                                signal                                s_reg                                ,                                s_next                                :                                std_logic_vector                                (                                N                                -                                1                                downto                                0                                );                                begin                                process                                (                                clk                                ,                                reset                                )                                begin                                if                                (                                reset                                =                                '1'                                )                                then                                s_reg                                <=                                (                                others                                =>                                '0'                                );                                -- clear the content                                elsif                                (                                clk                                'event                                and                                clk                                =                                '1'                                )                                then                                s_reg                                <=                                s_next                                ;                                -- otherwise save the next state                                end                                if                                ;                                end                                process                                ;                                process                                (                                ctrl                                ,                                s_reg                                )                                begin                                case                                ctrl                                is                                when                                "00"                                =>                                s_next                                <=                                s_reg                                ;                                -- no operation (to read data for serial to parallel)                                                                when                                "01"                                =>                                s_next                                <=                                data                                (                                N                                -                                1                                )                                &                                s_reg                                (                                N                                -                                1                                downto                                1                                );                                -- right shift                                when                                "10"                                =>                                s_next                                <=                                s_reg                                (                                N                                -                                2                                downto                                0                                )                                &                                data                                (                                0                                );                                -- left shift                                when                                others                                =>                                s_next                                <=                                data                                ;                                -- load data (for parallel to serial)                                end                                case                                ;                                end                                process                                ;                                q_reg                                <=                                s_reg                                ;                                end                                arch                                ;                              

11.3.2. Visual test¶

Listing 11.4 can be used to test the Listing 11.3 on the FPGA board. Here, 1 second clock pulse is used to visualize the output patterns. Here, outputs (i.e. q_reg) are displayed on LEDR; whereas 'shifting-control (i.e. ctrl)' and data-load (i.e. data) operations are performed using SW[16:15] and SW[7:0] respectively. Here, we can see the shifting of LEDR pattern towards right or left based on SW[16:15] combination. Please read Chapter 8 for better understanding of the listing.

Listing 11.4 Visual test : bidirectional shift register

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
                                                                -- shift_register_visualTest.vhd                                -- created by   :   Meher Krishna Patel                                -- date                 :   22-Dec-16                                -- SW[16:15] : used for control                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                entity                                shift_register_visualTest                                is                                generic                                (                                N                                :                                integer                                :=                                8                                );                                port                                (                                CLOCK_50                                ,                                reset                                :                                in                                std_logic                                ;                                SW                                :                                in                                std_logic_vector                                (                                16                                downto                                0                                );                                LEDR                                :                                out                                std_logic_vector                                (                                N                                -                                1                                downto                                0                                )                                );                                end                                shift_register_visualTest                                ;                                architecture                                arch                                of                                shift_register_visualTest                                is                                signal                                clk_Pulse1s                                :                                std_logic                                ;                                begin                                -- clock 1 s                                clock_1s                                :                                entity                                work                                .                                clockTick                                generic                                map                                (                                M                                =>                                50000000                                ,                                N                                =>                                26                                )                                port                                map                                (                                clk                                =>                                CLOCK_50                                ,                                reset                                =>                                reset                                ,                                clkPulse                                =>                                clk_Pulse1s                                );                                -- shift_register testing with 1 sec clock pulse                                shift_register_1s                                :                                entity                                work                                .                                shift_register                                generic                                map                                (                                N                                =>                                N                                )                                port                                map                                (                                clk                                =>                                clk_Pulse1s                                ,                                reset                                =>                                reset                                ,                                data                                =>                                SW                                (                                N                                -                                1                                downto                                0                                ),                                ctrl                                =>                                (                                SW                                (                                16                                downto                                15                                )),                                q_reg                                =>                                LEDR                                );                                end                                arch                                ;                              

11.3.3. Parallel to serial converter¶

If data is loaded first (i.e. ctrl = ''11''), and later shift operation is performed (i.e.. ctrl = ''01'' or ''10''); then Listing 11.3 will work as 'parallel to serial converter'. In Listing 11.5 shows the parallel to serial converter which is tested in Listing 11.8.

Listing 11.5 Parallel to serial converter

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
                                                                -- parallel_to_serial.vhd                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                entity                                parallel_to_serial                                is                                generic                                (                                N                                :                                integer                                :=                                8                                );                                port                                (                                clk                                ,                                reset                                :                                in                                std_logic                                ;                                data_in                                :                                in                                std_logic_vector                                (                                N                                -                                1                                downto                                0                                );                                -- parallel data                                data_out                                :                                out                                std_logic                                ;                                -- serial data                                empty_tick                                :                                out                                std_logic                                -- 1 = empty, to control other devices                                );                                end                                entity                                ;                                architecture                                arch                                of                                parallel_to_serial                                is                                type                                operation_type                                is                                (                                idle                                ,                                convert                                ,                                done                                );                                signal                                state_reg                                ,                                state_next                                :                                operation_type                                ;                                signal                                data_reg                                ,                                data_next                                :                                std_logic_vector                                (                                N                                -                                1                                downto                                0                                )                                :=                                (                                others                                =>                                '0'                                );                                signal                                count_reg                                ,                                count_next                                :                                unsigned                                (                                N                                -                                1                                downto                                0                                );                                begin                                -- current register values                                process                                (                                clk                                ,                                reset                                )                                begin                                if                                reset                                =                                '1'                                then                                state_reg                                <=                                idle                                ;                                data_reg                                <=                                (                                others                                =>                                '0'                                );                                count_reg                                <=                                (                                others                                =>                                '0'                                );                                elsif                                (                                clk                                'event                                and                                clk                                =                                '1'                                )                                then                                state_reg                                <=                                state_next                                ;                                data_reg                                <=                                data_next                                ;                                count_reg                                <=                                count_next                                ;                                end                                if                                ;                                end                                process                                ;                                -- next value in the register                                                                -- note that, it is poor style of coding as output data calculation                                -- and next values in register are calculated simultaneously. These                                -- should be done in different process statements.                                                                process                                (                                state_reg                                ,                                data_in                                ,                                count_reg                                ,                                data_reg                                )                                begin                                empty_tick                                <=                                '0'                                ;                                state_next                                <=                                state_reg                                ;                                data_next                                <=                                data_reg                                ;                                count_next                                <=                                count_reg                                ;                                case                                state_reg                                is                                when                                idle                                =>                                state_next                                <=                                convert                                ;                                data_next                                <=                                data_in                                ;                                -- load the parallel data data                                empty_tick                                <=                                '1'                                ;                                count_next                                <=                                count_reg                                +                                1                                ;                                when                                convert                                =>                                count_next                                <=                                count_reg                                +                                1                                ;                                if                                count_reg                                =                                N                                then                                -- note that N is used here (not N-1, see reason below)                                -- serial_to_parallel.vhd needs one clock cycle to transfer the converted                                -- data (i.e. parallel data) to next device, therefore it can not update the                                -- current value immediatly after the conversion. Therefore, count_reg = N,                                                                -- is used in above line (instead of N-1), so that one extra bit will be added                                -- in the end and will be discarded by serial_to_parallel.vhd as it will not                                                                -- read the last value.                                -- Also, data_next is not defined here, as last bit is not, therefore, value of                                -- data_next at count 'N' will be same as at 'N-1'.                                                                state_next                                <=                                done                                ;                                else                                -- shift the data to right and append zero in the beginning                                data_next                                <=                                '0'                                &                                data_reg                                (                                N                                -                                1                                downto                                1                                );                                end                                if                                ;                                when                                done                                =>                                count_next                                <=                                (                                others                                =>                                '0'                                );                                state_next                                <=                                idle                                ;                                end                                case                                ;                                end                                process                                ;                                -- send bit to output port                                data_out                                <=                                data_reg                                (                                0                                );                                end                                arch                                ;                              

11.3.4. Serial to parallel converter¶

If shifting is performed first (i.e.. ctrl = ''01'' or ''10''), and later data is read (i.e. ctrl = ''00''); then Listing 11.3 will work as 'serial to parallel converter'. In Listing 11.6 shows the serial to parallel converter which is tested in Listing 11.8.

Listing 11.6 Serial to parallel converter

                                1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100 101 102 103
                                                                -- serial_to_parallel.vhd                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                entity                                serial_to_parallel                                is                                generic                                (                                N                                :                                natural                                :=                                4                                );                                port                                (                                clk                                ,                                reset                                :                                in                                std_logic                                ;                                in_tick                                :                                in                                std_logic                                ;                                -- input tick to control the conversion from other device                                din                                :                                in                                std_logic                                ;                                load                                :                                out                                std_logic                                ;                                -- use it as tick, to load data immidiately e.g. from FIFO                                done                                :                                out                                std_logic                                ;                                -- use it as tick, if data is obtained after one-clock cycle e.g. from generators                                dout                                :                                out                                std_logic_vector                                (                                N                                -                                1                                downto                                0                                )                                );                                end                                entity                                serial_to_parallel                                ;                                architecture                                arch                                of                                serial_to_parallel                                is                                type                                state                                is                                (                                idle                                ,                                store0                                ,                                store1                                );                                signal                                state_reg                                ,                                state_next                                :                                state                                ;                                signal                                y_reg                                ,                                y_next                                :                                std_logic_vector                                (                                N                                -                                1                                downto                                0                                );                                signal                                i_reg                                ,                                i_next                                :                                natural                                range                                0                                to                                N                                ;                                begin                                -- update registers                                process                                (                                clk                                ,                                reset                                )                                begin                                if                                (                                reset                                =                                '1'                                )                                then                                i_reg                                <=                                0                                ;                                y_reg                                <=                                (                                others                                =>                                '0'                                );                                elsif                                rising_edge                                (                                clk                                )                                then                                i_reg                                <=                                i_next                                ;                                y_reg                                <=                                y_next                                ;                                end                                if                                ;                                end                                process                                ;                                -- update states                                process                                (                                clk                                ,                                reset                                )                                begin                                if                                reset                                =                                '1'                                then                                state_reg                                <=                                idle                                ;                                elsif                                rising_edge                                (                                clk                                )                                then                                state_reg                                <=                                state_next                                ;                                end                                if                                ;                                end                                process                                ;                                -- output data calculation                                process                                (                                clk                                ,                                din                                ,                                y_next                                ,                                i_next                                ,                                i_reg                                ,                                y_reg                                ,                                state_reg                                ,                                state_next                                )                                begin                                y_next                                <=                                y_reg                                ;                                case                                state_reg                                is                                when                                idle                                =>                                i_next                                <=                                0                                ;                                load                                <=                                '1'                                ;                                done                                <=                                '0'                                ;                                -- this loop is used to load the data immidiately in the registers                                if                                in_tick                                =                                '1'                                and                                din                                =                                '0'                                then                                -- i.e. if first value is zero                                state_next                                <=                                store0                                ;                                -- then go to store0                                elsif                                in_tick                                =                                '1'                                and                                din                                =                                '1'                                then                                -- i.e. if first value is one                                state_next                                <=                                store1                                ;                                -- then go to store1                                else                                state_next                                <=                                idle                                ;                                end                                if                                ;                                -- input data is 0.                                when                                store0                                =>                                i_next                                <=                                i_reg                                +                                1                                ;                                y_next                                (                                i_reg                                )                                <=                                '0'                                ;                                load                                <=                                '0'                                ;                                done                                <=                                '0'                                ;                                if                                i_reg                                =                                N                                -                                1                                then                                state_next                                <=                                idle                                ;                                done                                <=                                '1'                                ;                                elsif                                din                                =                                '1'                                then                                state_next                                <=                                store1                                ;                                else                                state_next                                <=                                store0                                ;                                end                                if                                ;                                -- input data is 1.                                                                when                                store1                                =>                                i_next                                <=                                i_reg                                +                                1                                ;                                y_next                                (                                i_reg                                )                                <=                                '1'                                ;                                load                                <=                                '0'                                ;                                done                                <=                                '0'                                ;                                if                                i_reg                                =                                N                                -                                1                                then                                state_next                                <=                                idle                                ;                                done                                <=                                '1'                                ;                                elsif                                din                                =                                '0'                                then                                state_next                                <=                                store0                                ;                                else                                state_next                                <=                                store1                                ;                                end                                if                                ;                                end                                case                                ;                                end                                process                                ;                                -- send data to output                                dout                                <=                                y_next                                when                                i_reg                                =                                N                                -                                1                                ;                                end                                architecture                                arch                                ;                              

11.3.5. Top level connection between serial and parallel converters¶

In Listing 11.7, the parallel-counter-data is converted into serial data using Listing 11.5. Then received serial data is converted back to parallel data by Listing 11.6. The simulation results are shown in Fig. 11.4

Listing 11.7 Connection between serial and parallel converters

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
                                                                -- parallel_and_serial_top_v1.vhd                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                library                                work                                ;                                entity                                parallel_and_serial_top_v1                                is                                generic                                (                                M                                :                                integer                                :=                                11                                ;                                -- count upto M                                N                                :                                integer                                :=                                4                                );                                -- N bits required to count to M                                port                                (                                reset                                :                                in                                std_logic                                ;                                clk                                :                                in                                std_logic                                ;                                data_out                                :                                out                                std_logic_vector                                (                                3                                downto                                0                                );                                data_in                                :                                out                                std_logic_vector                                (                                3                                downto                                0                                )                                );                                end                                parallel_and_serial_top_v1                                ;                                architecture                                arch                                of                                parallel_and_serial_top_v1                                is                                signal                                count                                :                                std_logic_vector                                (                                3                                downto                                0                                );                                signal                                dout                                :                                std_logic                                ;                                signal                                e_tick                                :                                std_logic                                ;                                signal                                not_e_tick                                :                                std_logic                                ;                                begin                                -- register is not empty i.e. read data on this tick                                not_e_tick                                <=                                not                                (                                e_tick                                );                                -- generated count on data_out, whereas received count on data_out                                data_in                                <=                                count                                ;                                -- parallel to serial conversion                                unit_p_to_s                                :                                entity                                work                                .                                parallel_to_serial                                generic                                map                                (                                N                                =>                                N                                )                                port                                map                                (                                clk                                =>                                clk                                ,                                reset                                =>                                reset                                ,                                data_in                                =>                                count                                ,                                data_out                                =>                                dout                                ,                                empty_tick                                =>                                e_tick                                );                                -- serial to parallel conversion                                unit_s_to_p                                :                                entity                                work                                .                                serial_to_parallel                                generic                                map                                (                                N                                =>                                N                                )                                port                                map                                (                                clk                                =>                                clk                                ,                                reset                                =>                                reset                                ,                                in_tick                                =>                                not_e_tick                                ,                                din                                =>                                dout                                ,                                dout                                =>                                data_out                                );                                -- modMCounter to generate data (i.e. count) for transmission                                unit_counter                                :                                entity                                work                                .                                modMCounter                                generic                                map                                (                                M                                =>                                M                                ,                                N                                =>                                N                                )                                port                                map                                (                                clk                                =>                                e_tick                                ,                                reset                                =>                                reset                                ,                                count                                =>                                count                                );                                end                                arch                                ;                              

../_images/parallel_and_serial_top_v1.jpg

Fig. 11.4 Simulation results for Listing 11.7

11.3.6. Visual test for serial and parallel converters¶

In Listing 11.8, the reduced clock-rate is applied to Listing 11.7, so that output can be seen on LEDs. Here, generated counter outputs are displayed on LEDG, whereas the received outputs (i.e. after conversion) are displayed on LEDG.

Listing 11.8 Visual test for serial and parallel converters

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
                                                                -- parallel_and_serial_top_visual_v1.vhd                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                library                                work                                ;                                entity                                parallel_and_serial_top_visual_v1                                is                                port                                (                                reset                                :                                in                                std_logic                                ;                                CLOCK_50                                :                                in                                std_logic                                ;                                -- generated count displayed on LEDG                                LEDG                                :                                out                                std_logic_vector                                (                                3                                downto                                0                                );                                -- received count displayed on LEDR                                LEDR                                :                                out                                std_logic_vector                                (                                3                                downto                                0                                )                                );                                end                                parallel_and_serial_top_visual_v1                                ;                                architecture                                arch                                of                                parallel_and_serial_top_visual_v1                                is                                signal                                clk                                :                                std_logic                                ;                                begin                                -- parallel and serial conversion test                                unit_p_and_s                                :                                entity                                work                                .                                parallel_and_serial_top_v1                                generic                                map                                (                                M                                =>                                7                                ,                                N                                =>                                4                                )                                port                                map                                (                                clk                                =>                                clk                                ,                                reset                                =>                                reset                                ,                                data_in                                =>                                LEDR                                ,                                data_out                                =>                                LEDG                                );                                -- clock tick to see outputs on LEDs                                unit_clkTick                                :                                entity                                work                                .                                clocktick                                generic                                map                                (                                M                                =>                                5000000                                ,                                N                                =>                                23                                )                                port                                map                                (                                clk                                =>                                clock_50                                ,                                reset                                =>                                reset                                ,                                clkpulse                                =>                                clk                                );                                end                                arch                                ;                              

11.4. Random access memory (RAM)¶

RAM is memory cells which are used to store or retrieve the data. Further, FPGA chips have separate RAM modules which can be used to design memories of different sizes and types, as shown in this section. VHDL files required for this example are listed below,

  • single_port_RAM.vhd
  • single_port_RAM_visualTest.vhd
  • dual_port_RAM.vhd
  • dual_port_RAM_visualTest.vhd

11.4.1. Single port RAM¶

Single port RAM has one input port (i.e. address line) which is used for both storing and retrieving the data, as shown in Fig. 11.5. Here 'addr[1:0]' port is used for both 'read' and 'write' operations. Listing 11.9 is used to generate this design.

../_images/single_port_RAM.jpg

Fig. 11.5 RTL view : Single port RAM (Listing 11.9)

Explanation Listing 11.9

In the listing port 'addr' (Line 31) is 2 bit wide as 'addr_width' is set to 2 (Line 24). Therefore, total '4 elements (i.e. \(2^2\))' can be stored in the RAM. Further, 'din' port (Line 32) is 3 bit wide as 'data_width' is set to 3 (Line 25); which means the data should be 3 bit wide. In summary, current RAM-designs can store '4 elements' in it and each elements should be 3-bit wide.

Write enable (we) port should be high and low for storing and retrieving the data respectively. 'din' port is used to write the data in the memory; whereas 'dout' port is used for reading the data from the memory. In Lines 43-48, the write operation is performed on rising edge of the clock; whereas read operation is performed at Line 53.

Note that, 'ram_type' (Line 38) is created using integer array (as 'addr_width' is integer at Line 2); whereas 'addr' port is of 'std_logic_vector' type (Line 31). Therefore, type conversion is required during write and read operations at Lines 46 and 53 respectively. Further, the type 'std_logic_vector' can not be converted directly to 'integer', therefore it is converted to 'unsigned' type before converting to 'integer'.

Lastly, Fig. 11.6 shows the simulation results for the design. Here, 'we' is set to 1 after first cursor and the data is written at three different addresses (not 4). Next, 'we' is set to 0 after second cursor and read operations are performed for all addresses. Since, no values is stored for address '10', therefore dout is displayed as 'UUU' for this address as shown after third cursor.

../_images/single_port_RAM_Wave.jpg

Fig. 11.6 Simulation results : Single port RAM (Listing 11.9)

Listing 11.9 Single port RAM

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
                                                                -- single_port_RAM.vhd                                -- created by   :   Meher Krishna Patel                                -- date         :   26-Dec-16                                -- Functionality:                                -- store and retrieve data from single port RAM                                -- ports:                                -- we   : write enable                                -- addr : input port for getting address                                -- din : input data to be stored in RAM                                -- data : output data read from RAM                                -- addr_width : total number of elements to store (put exact number)                                -- addr_bits  : bits requires to store elements specified by addr_width                                -- data_width : number of bits in each elements                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                entity                                single_port_RAM                                is                                generic                                (                                addr_width                                :                                integer                                :=                                2                                ;                                data_width                                :                                integer                                :=                                3                                );                                port                                (                                clk                                :                                in                                std_logic                                ;                                we                                :                                in                                std_logic                                ;                                addr                                :                                in                                std_logic_vector                                (                                addr_width                                -                                1                                downto                                0                                );                                din                                :                                in                                std_logic_vector                                (                                data_width                                -                                1                                downto                                0                                );                                dout                                :                                out                                std_logic_vector                                (                                data_width                                -                                1                                downto                                0                                )                                );                                end                                single_port_RAM                                ;                                architecture                                arch                                of                                single_port_RAM                                is                                type                                ram_type                                is                                array                                (                                2                                **                                addr_width                                -                                1                                downto                                0                                )                                of                                std_logic_vector                                (                                data_width                                -                                1                                downto                                0                                );                                signal                                ram_single_port                                :                                ram_type                                ;                                begin                                process                                (                                clk                                )                                begin                                if                                (                                clk                                'event                                and                                clk                                =                                '1'                                )                                then                                if                                (                                we                                =                                '1'                                )                                then                                -- write data to address 'addr'                                --convert 'addr' type to integer from std_logic_vector                                ram_single_port                                (                                to_integer                                (                                unsigned                                (                                addr                                )))                                <=                                din                                ;                                end                                if                                ;                                end                                if                                ;                                end                                process                                ;                                -- read data from address 'addr'                                -- convert 'addr' type to integer from std_logic_vector                                dout                                <=                                ram_single_port                                (                                to_integer                                (                                unsigned                                (                                addr                                )));                                end                                arch                                ;                              

11.4.2. Visual test : single port RAM¶

Listing 11.10 can be use to test the Listing 11.9 on FPGA board. Different combination of switches can be used to store and retrieve the data from RAM. These data will be displayed on LEDs during read operations.

Listing 11.10 Visual test : single port RAM

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
                                                                -- single_port_RAM_visualTest.vhd                                -- created by   :   Meher Krishna Patel                                -- date         :   26-Dec-16                                -- Functionality:                                -- store and retrieve data from single port RAM                                -- ports:                                -- Write Enable (we)    : SW[16]                                -- Address (addr)           : SW[15-14]                                -- din                              : SW[2:0]                                -- dout                             : LEDR                                use                                ieee.numeric_std.                                all                                ;                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                entity                                single_port_RAM_visualTest                                is                                generic                                (                                ADDR_WIDTH                                :                                integer                                :=                                2                                ;                                DATA_WIDTH                                :                                integer                                :=                                3                                );                                port                                (                                CLOCK_50                                :                                in                                std_logic                                ;                                SW                                :                                in                                std_logic_vector                                (                                16                                downto                                0                                );                                LEDR                                :                                out                                std_logic_vector                                (                                DATA_WIDTH                                -                                1                                downto                                0                                )                                );                                end                                single_port_RAM_visualTest                                ;                                architecture                                arch                                of                                single_port_RAM_visualTest                                is                                begin                                single_port_RAM_test                                :                                entity                                work                                .                                single_port_RAM                                port                                map                                (                                clk                                =>                                CLOCK_50                                ,                                we                                =>                                SW                                (                                16                                ),                                addr                                =>                                SW                                (                                15                                downto                                14                                ),                                din                                =>                                SW                                (                                2                                downto                                0                                ),                                dout                                =>                                LEDR                                );                                end                                arch                                ;                              

11.4.3. Dual port RAM¶

In single port RAM, the same 'addr' port is used for read and write operations; whereas in dual port RAM dedicated address lines are provided for read and write operations i.e. 'addr_rd' and 'addr_wr' respectively, as shown in Fig. 11.7. Also, the listing can be further modified to allow read and write operation through both the ports.

../_images/dual_port_RAM.jpg

Fig. 11.7 Dual port RAM

Listing 11.11 is used to implement Fig. 11.7, which is same as Listing 11.9 with three changes. First, two address ports are used at Line 32 (i.e. 'addr_rd' and 'addr_wr') instead of one. Next, 'addr_wr' is used to write the data at Line 47; whereas 'addr_rd' data is used to retrieve the data at Line 54. Hence, read and write operation can be performed simultaneously using these two address lines.

Fig. 11.8 shows the simulation results for dual port RAM. Here, on the first cursor, '011' is written at address '01'. On next cursor, this value is read along with writing operation as location '10'. Lastly, last two cursor shows that if read and write operation is performed simultaneously on one address e.g. '01', then new data will be available at 'dout' port after one clock cycle.

../_images/dual_port_RAM_wave.jpg

Fig. 11.8 Simulation results : Dual port RAM (Listing 11.11)

Listing 11.11 Dual port RAM

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
                                                                -- dual_port_RAM.vhd                                -- created by   :   Meher Krishna Patel                                -- date         :   26-Dec-16                                -- Functionality:                                -- store and retrieve data from single port RAM                                -- ports:                                -- we         : write enable                                -- addr_wr    : address for writing data                                -- addr_rd     : address for reading                                -- din        : input data to be stored in RAM                                -- data       : output data read from RAM                                -- addr_width : total number of elements to store (put exact number)                                -- addr_bits  : bits requires to store elements specified by addr_width                                -- data_width : number of bits in each elements                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                entity                                dual_port_RAM                                is                                generic                                (                                addr_width                                :                                integer                                :=                                2                                ;                                data_width                                :                                integer                                :=                                3                                );                                port                                (                                clk                                :                                in                                std_logic                                ;                                we                                :                                in                                std_logic                                ;                                addr_wr                                ,                                addr_rd                                :                                in                                std_logic_vector                                (                                addr_width                                -                                1                                downto                                0                                );                                din                                :                                in                                std_logic_vector                                (                                data_width                                -                                1                                downto                                0                                );                                dout                                :                                out                                std_logic_vector                                (                                data_width                                -                                1                                downto                                0                                )                                );                                end                                dual_port_RAM                                ;                                architecture                                arch                                of                                dual_port_RAM                                is                                type                                ram_type                                is                                array                                (                                2                                **                                addr_width                                -                                1                                downto                                0                                )                                of                                std_logic_vector                                (                                data_width                                -                                1                                downto                                0                                );                                signal                                ram_dual_port                                :                                ram_type                                ;                                begin                                process                                (                                clk                                )                                begin                                if                                (                                clk                                'event                                and                                clk                                =                                '1'                                )                                then                                if                                (                                we                                =                                '1'                                )                                then                                -- write data to address 'addr_wr'                                -- convert 'addr_wr' type to integer from std_logic_vector                                ram_dual_port                                (                                to_integer                                (                                unsigned                                (                                addr_wr                                )))                                <=                                din                                ;                                end                                if                                ;                                end                                if                                ;                                end                                process                                ;                                -- get address for reading data from 'addr_rd'                                -- convert 'addr_rd' type to integer from std_logic_vector                                dout                                <=                                ram_dual_port                                (                                to_integer                                (                                unsigned                                (                                addr_rd                                )));                                end                                arch                                ;                              

11.4.4. Visual test : dual port RAM¶

Listing 11.12 can be use to test the Listing 11.11 on FPGA board. Different combination of switches can be used to store and retrieve the data from RAM. These data will be displayed on LEDs during read operations.

Listing 11.12 Visual test : dual port RAM

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
                                                                -- dual_port_RAM_visualTest.vhd                                -- created by   :   Meher Krishna Patel                                -- date         :   26-Dec-16                                -- Functionality:                                -- store and retrieve data from dual port RAM                                -- ports:                                -- Write Enable (we) : SW[16]                                -- Address (addr_wr)    : SW[15-14]                                -- Address (addr_rd)    : SW[13-12]                                -- din                      : SW[2:0]                                -- dout                 : LEDR                                use                                ieee.numeric_std.                                all                                ;                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                entity                                dual_port_RAM_visualTest                                is                                generic                                (                                ADDR_WIDTH                                :                                integer                                :=                                2                                ;                                DATA_WIDTH                                :                                integer                                :=                                3                                );                                port                                (                                CLOCK_50                                :                                in                                std_logic                                ;                                SW                                :                                in                                std_logic_vector                                (                                16                                downto                                0                                );                                LEDR                                :                                out                                std_logic_vector                                (                                DATA_WIDTH                                -                                1                                downto                                0                                )                                );                                end                                dual_port_RAM_visualTest                                ;                                architecture                                arch                                of                                dual_port_RAM_visualTest                                is                                begin                                dual_port_RAM_test                                :                                entity                                work                                .                                dual_port_RAM                                port                                map                                (                                clk                                =>                                CLOCK_50                                ,                                we                                =>                                SW                                (                                16                                ),                                addr_wr                                =>                                SW                                (                                15                                downto                                14                                ),                                addr_rd                                =>                                SW                                (                                13                                downto                                12                                ),                                din                                =>                                SW                                (                                2                                downto                                0                                ),                                dout                                =>                                LEDR                                );                                end                                arch                                ;                              

language = Vhdl, label = {} ]{.vhd}

11.5. Read only memory (ROM)¶

ROMs are the devices which are used to store information permanently. In this section, ROM is implemented on FPGA to store the display-pattern for seven-segment device, which is explained in Section 8.5. VHDL files required for this example are listed below,

  • ROM_sevenSegment.vhd
  • ROM_sevenSegment_visualTest.vhd

11.5.1. ROM implementation using RAM (block ROM)¶

Listing 11.13 implements the ROM using a block of RAM, which stores the seven-segment display pattern in it. Fig. 11.9 shows the RTL view of the listing, where ROM is implemented using synchronous RAM (denoted by 'SYNC RAM' in the figure).

Note that, the 'write enable (WE)' port is not provided in the implementation, therefore 'WE' is set to '0' permanently (see Fig. 11.9); hence, new data can not be written in the RAM. And data stored during initialization of RAM will be stored permanently. Therefore, the RAM can be considered as ROM. This implementation of ROM is also referred as 'block ROM'.

../_images/ROM_using_RAM.jpg

Fig. 11.9 RTL view : block ROM (Listing 11.13)

Explanation Listing 11.13

Data from the ROM is accessed through address line; therefore two ports are provided in the design i.e. addr and data (Lines 27-28). 'addr_width' (Line 22) is the number of addresses, which corresponds to total number elements to be stored. Further, 'addr_bits' (Line 23) is also defined, which is the minimum number of bits required to represent the total number of addresses i.e. 'addr_width'. Lastly, 'data_width' is declared at Line 24, which defines the number of bits in each element.

Line 34 defines the ROM type (named as rom_type) i.e. ROM has 16 elements (i.e. addr_width) and each element contains 7 bits (i.e. data_width). Next in Line 36, a ROM is created (named as sevenSegment_ROM) of type 'rom_type'; and patterns for seven-segment display are inserted in Lines 37-52 (see Section 8.5 for details). These values are stored sequentially in ROM i.e. patterns 0, A and F are stored at location 0, 10 and 15 respectively.

Note that, ROM is created using 'integer' data type (see Line 22 and 34); whereas address line 'addr' has type 'std_logic_vector'. Therefore, to read the memory location, the 'addr' value must be changed to 'integer' which is done at Line 55. Since 'std_logic_vector' can not be converted directly to integer, therefore it is changed to 'unsigned' first, and then converted to 'integer'.

In summary, input 'addr' is the 'binary' address, which is converted into ''integer' format. Then ROM element is accessed based on this 'integer' address, which is finally provided at the output port i.e. 'data'. Fig. 11.10 shows the retrieved 'data' values from the ROM for different 'addr' values e.g. last waveform presents that 'addr' is '1111' and the corresponding 'data' value is '0111000'.

../_images/ROM_sevenSegment.jpg

Fig. 11.10 Retrieving data from ROM

Listing 11.13 Seven segment display pattern stored in ROM

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
                                                                --ROM_sevenSegment.vhd                                -- created by   :   Meher Krishna Patel                                -- date                 :   25-Dec-16                                -- Functionality:                                -- seven-segment display format for Hexadecimal values (i.e. 0-F) are stored in ROM                                                                -- ports:                                -- addr             : input port for getting address                                -- data             : ouput data at location 'addr'                                -- addr_width : total number of elements to store (put exact number)                                -- addr_bits  : bits requires to store elements specified by addr_width                                -- data_width : number of bits in each elements                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                entity                                ROM_sevenSegment                                is                                generic                                (                                addr_width                                :                                integer                                :=                                16                                ;                                -- store 16 elements                                addr_bits                                :                                integer                                :=                                4                                ;                                -- required bits to store 16 elements                                data_width                                :                                integer                                :=                                7                                -- each element has 7-bits                                );                                port                                (                                addr                                :                                in                                std_logic_vector                                (                                addr_bits                                -                                1                                downto                                0                                );                                data                                :                                out                                std_logic_vector                                (                                data_width                                -                                1                                downto                                0                                )                                );                                end                                ROM_sevenSegment                                ;                                architecture                                arch                                of                                ROM_sevenSegment                                is                                type                                rom_type                                is                                array                                (                                0                                to                                addr_width                                -                                1                                )                                of                                std_logic_vector                                (                                data_width                                -                                1                                downto                                0                                );                                signal                                sevenSegment_ROM                                :                                rom_type                                :=                                (                                "1000000"                                ,                                -- 0, active low i.e. 0:display & 1:no display                                "1111001"                                ,                                -- 1                                "0100100"                                ,                                -- 2                                "0110000"                                ,                                -- 3                                "0011001"                                ,                                -- 4                                "0010010"                                ,                                -- 5                                "0000010"                                ,                                -- 6                                "1111000"                                ,                                -- 7                                "0000000"                                ,                                -- 8                                "0010000"                                ,                                -- 9                                "0001000"                                ,                                -- a                                "0000011"                                ,                                -- b                                "1000110"                                ,                                -- c                                "0100001"                                ,                                -- d                                "0000110"                                ,                                -- e                                "0001110"                                -- f                                );                                begin                                data                                <=                                sevenSegment_ROM                                (                                to_integer                                (                                unsigned                                (                                addr                                )));                                end                                arch                                ;                              

11.5.2. ROM implementation logic cells (distributed ROM)¶

Note that, in Line 36 of Listing 11.13, the 'signal' keywords is used for 'sevenSegment_ROM', which stores the constant values in Lines 37-52. If the 'signal' keyword is replaced by 'constant', then the design will be implemented using logical cells i.e. with 'Mux' as presented in Fig. 11.11 (instead of block RAM). This design is referred as 'distributed ROM'.

../_images/ROM_using_logic_cells.jpg

Fig. 11.11 Partial RTL view : distributed ROM (modified Listing 11.13)

11.5.3. Distributed ROM vs Block ROM¶

Note that, Fig. 11.11 illustrate that large number of logical cells are required for distributed ROM implementation; hence it may result in lack of resources for implementing other logical designs.

Further, block RAM is the memory module which is embedded in the FPGA device. Therefore, ROM implementation using RAM does not use the regular logic cells; hence block ROM is the preferred way to implement the ROM as discussed in Section 11.5.1.

11.5.4. Visual test¶

Listing 11.14 is provided the input 'addr' through switches 'SW' (Line 20) and then output is from Listing 11.13 is received to signal 'data' (Lines 31-32); which is finally displayed on seven segment display devices (Line 34) and LEDs (Line 35). Here, we can see the switch value on the seven-segment display devices along with the ROM content on LEDs; e.g. if SW value is '011' then '3' will be displayed on seven-segment display and '0000110' will be displayed on LEDs.

Listing 11.14 Display ROM data on seven segment display and LEDs

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
                                                                -- ROM_sevenSegment_visualTest.vhd                                -- created by   :   Meher Krishna Patel                                -- date                 :   25-Dec-16                                -- Functionality:                                -- retrieve data from ROM and display on seven-segment device and LEDs                                -- ports:                                -- SW : address in binary format                                -- HEX0 : display data on seven segment device                                -- LEDR : display data on LEDs                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                entity                                ROM_sevenSegment_visualTest                                is                                port                                (                                SW                                :                                in                                std_logic_vector                                (                                3                                downto                                0                                );                                HEX0                                :                                out                                std_logic_vector                                (                                6                                downto                                0                                );                                LEDR                                :                                out                                std_logic_vector                                (                                6                                downto                                0                                )                                );                                end                                ROM_sevenSegment_visualTest                                ;                                architecture                                arch                                of                                ROM_sevenSegment_visualTest                                is                                -- signal to store received data, so that it can be displayed on                                                                -- two devices i.e. seven segment display and LEDs                                signal                                data                                :                                std_logic_vector                                (                                6                                downto                                0                                );                                begin                                seven_segment_ROM                                :                                entity                                work                                .                                ROM_sevenSegment                                port                                map                                (                                addr                                =>                                SW                                ,                                data                                =>                                data                                );                                HEX0                                <=                                data                                ;                                -- display on seven segment devices                                LEDR                                <=                                data                                ;                                -- display on LEDs                                end                                arch                                ;                              

11.5.5. Defining ROM contents in file¶

We can define the content of the ROM in the separate file and then read this file using VHDL code. Please note following items about this style,

  • The code will become device specific because Altera devices support the '.mif' files whereas Xilinx devices support the '.CGF' files, which have different formats for storing the ROM contents.
  • Design can not be simulated directly using Modelsim.

Since, we are using 'Quartus software' in this tutorial, therefore '.mif' files are discussed in this section. ROM data is defined in 'seven_seg_data.mif' file as shown in Listing 11.15. In '.mif' file, the comments are written between two '% %' signs (both single line e.g. Line 1 and multiline e.g. Lines 8-12). Further, we need to define certain parameters i.e. data and address types (see comments for details). Lastly, at Line 18, we set the values at all the addresses as '0' and then values are assigned at each address. This can be useful, when we want to store data at fewer locations.

Next, Listing 11.16 is same as the Listing 11.13 except Lines 35-41 where ROM data is read from the '.mif file', instead of defining in the same file. Please read the comments for understand these lines.

Finally, Listing 11.17 is exactly same as Listing 11.14 except Listing 11.16 is instantiated at Line 31.

Listing 11.15 ROM data stored in '.mif file'

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
                                                                % seven_seg_data.mif %                                % ROM data for seven segment display %                                % data width and total data %                                width                                =                                7                                ;                                % number of bits in each data %                                depth                                =                                16                                ;                                % total number of data (i.e. total address) %                                %                                                                format                                of                                data                                and                                address                                stored                                in                                this                                file                                uns                                :                                unsigned                                ,                                dec                                :                                decimal                                ,                                hex                                :                                hexadecimal                                bin                                :                                binary                                ,                                oct                                :                                octal                                %                                address_radix                                =                                uns                                ;                                % address is unsigned-type %                                data_radix                                =                                bin                                ;                                % data is binary-type %                                % ROM data %                                content                                begin                                [                                0.                                .                                15                                ]                                :                                0000000                                ;                                % optional : assign 0 to all address %                                0                                :                                1000000                                ;                                % format => signed : binary %                                1                                :                                1111001                                ;                                2                                :                                0100100                                ;                                3                                :                                0110000                                ;                                4                                :                                0011001                                ;                                5                                :                                0010010                                ;                                6                                :                                0000010                                ;                                7                                :                                1111000                                ;                                8                                :                                0000000                                ;                                9                                :                                0010000                                ;                                10                                :                                0001000                                ;                                11                                :                                0000011                                ;                                12                                :                                1000110                                ;                                13                                :                                0100001                                ;                                14                                :                                0000110                                ;                                15                                :                                0001110                                ;                                end                                ;                              

Listing 11.16 VHDL code to read '.mif' file

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
                                                                --ROM_sevenSegment_mif.vhd                                -- created by   :   Meher Krishna Patel                                -- date                 :   25-Dec-16                                -- Functionality:                                -- seven-segment display format for Hexadecimal values (i.e. 0-F) are stored in ROM                                                                -- ports:                                -- addr             : input port for getting address                                -- data             : ouput data at location 'addr'                                -- addr_width : total number of elements to store (put exact number)                                -- addr_bits  : bits requires to store elements specified by addr_width                                -- data_width : number of bits in each elements                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                entity                                ROM_sevenSegment_mif                                is                                generic                                (                                addr_width                                :                                integer                                :=                                16                                ;                                -- store 16 elements                                addr_bits                                :                                integer                                :=                                4                                ;                                -- required bits to store 16 elements                                data_width                                :                                integer                                :=                                7                                -- each element has 7-bits                                );                                port                                (                                addr                                :                                in                                std_logic_vector                                (                                addr_bits                                -                                1                                downto                                0                                );                                data                                :                                out                                std_logic_vector                                (                                data_width                                -                                1                                downto                                0                                )                                );                                end                                ROM_sevenSegment_mif                                ;                                architecture                                arch                                of                                ROM_sevenSegment_mif                                is                                type                                rom_type                                is                                array                                (                                0                                to                                addr_width                                -                                1                                )                                of                                std_logic_vector                                (                                data_width                                -                                1                                downto                                0                                );                                signal                                sevenSegment_ROM                                :                                rom_type                                ;                                -- note that 'ram_init_file' is not the user-defined-name (it is attribute name)                                attribute                                ram_init_file                                :                                string                                ;                                -- "seven_seg_data.mif" is the relative address with respect to project directory                                -- suppose ".mif" file is saved in folder "ROM", then use "ROM/seven_seg_data.mif"                                attribute                                ram_init_file                                of                                sevenSegment_ROM                                :                                signal                                is                                "seven_seg_data.mif"                                ;                                begin                                data                                <=                                sevenSegment_ROM                                (                                to_integer                                (                                unsigned                                (                                addr                                )));                                end                                arch                                ;                              

Listing 11.17 Top level design for Listing 11.16

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
                                                                -- ROM_sevenSegment_mif_visualTest.vhd                                -- created by   :   Meher Krishna Patel                                -- date                 :   25-Dec-16                                -- Functionality:                                -- retrieve data from ROM and display on seven-segment device and LEDs                                -- ports:                                -- SW : address in binary format                                -- HEX0 : display data on seven segment device                                -- LEDR : display data on LEDs                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                entity                                ROM_sevenSegment_mif_visualTest                                is                                port                                (                                SW                                :                                in                                std_logic_vector                                (                                3                                downto                                0                                );                                HEX0                                :                                out                                std_logic_vector                                (                                6                                downto                                0                                );                                LEDR                                :                                out                                std_logic_vector                                (                                6                                downto                                0                                )                                );                                end                                ROM_sevenSegment_mif_visualTest                                ;                                architecture                                arch                                of                                ROM_sevenSegment_mif_visualTest                                is                                -- signal to store received data, so that it can be displayed on                                                                -- two devices i.e. seven segment display and LEDs                                signal                                data                                :                                std_logic_vector                                (                                6                                downto                                0                                );                                begin                                seven_segment_ROM                                :                                entity                                work                                .                                ROM_sevenSegment_mif                                port                                map                                (                                addr                                =>                                SW                                ,                                data                                =>                                data                                );                                HEX0                                <=                                data                                ;                                -- display on seven segment devices                                LEDR                                <=                                data                                ;                                -- display on LEDs                                end                                arch                                ;                              

11.6. LCD interface¶

In this section, a package is defined in Listing 11.18 which converts the binary data into seven-segment-display-format and lcd-data-format.

11.6.1. Example 1¶

In Listing 11.19, this package is used to display the value provided by the switches on the seven-segment device and on the LCD. Further, the counting-pattern is also displayed on the LCD screen. The ASCII-values are shown in Fig. 11.12 which are used for displaying values on LCD screen. Note that, a clock divider is implemented in the design at Lines 85-100. Please see the comments for more details.

../_images/asciiValues.jpg

Fig. 11.12 Chart : ASCII values

Listing 11.18 Package for converting binary-format into seven-segment and ASCII format

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
                                                                -- LCD_SSD_display_pkg.vhd                                -- LCD and Seven-segment-display                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                package                                LCD_SSD_display_pkg                                is                                -- binary to seven-segment format                                function                                binary_to_ssd                                (                                signal                                switch                                :                                unsigned                                )                                return                                unsigned                                ;                                -- binary to LCD format                                function                                binary_to_lcd                                (                                signal                                switch                                :                                unsigned                                )                                return                                unsigned                                ;                                end                                LCD_SSD_display_pkg                                ;                                package                                body                                LCD_SSD_display_pkg                                is                                -- begin function "binary_to_ssd"                                function                                binary_to_ssd                                (                                -- list all input here                                signal                                switch                                :                                unsigned                                (                                3                                downto                                0                                )                                )                                -- only one value can be return                                return                                unsigned                                is                                variable                                sevenSegment                                :                                unsigned                                (                                6                                downto                                0                                );                                begin                                case                                switch                                is                                -- active low i.e. 0:display & 1:no display                                when                                "0000"                                =>                                sevenSegment                                :=                                "1000000"                                ;                                -- 0,                                                                when                                "0001"                                =>                                sevenSegment                                :=                                "1111001"                                ;                                -- 1                                when                                "0010"                                =>                                sevenSegment                                :=                                "0100100"                                ;                                -- 2                                when                                "0011"                                =>                                sevenSegment                                :=                                "0110000"                                ;                                -- 3                                                                when                                "0100"                                =>                                sevenSegment                                :=                                "0011001"                                ;                                -- 4                                when                                "0101"                                =>                                sevenSegment                                :=                                "0010010"                                ;                                -- 5                                when                                "0110"                                =>                                sevenSegment                                :=                                "0000010"                                ;                                -- 6                                when                                "0111"                                =>                                sevenSegment                                :=                                "1111000"                                ;                                -- 7                                when                                "1000"                                =>                                sevenSegment                                :=                                "0000000"                                ;                                -- 8                                when                                "1001"                                =>                                sevenSegment                                :=                                "0010000"                                ;                                -- 9                                when                                "1010"                                =>                                sevenSegment                                :=                                "0001000"                                ;                                -- a                                when                                "1011"                                =>                                sevenSegment                                :=                                "0000011"                                ;                                -- b                                when                                "1100"                                =>                                sevenSegment                                :=                                "1000110"                                ;                                -- c                                when                                "1101"                                =>                                sevenSegment                                :=                                "0100001"                                ;                                -- d                                when                                "1110"                                =>                                sevenSegment                                :=                                "0000110"                                ;                                -- e                                when                                others                                =>                                sevenSegment                                :=                                "0001110"                                ;                                -- f                                end                                case                                ;                                return                                sevenSegment                                ;                                end                                binary_to_ssd                                ;                                -- end function "binary_to_ssd"                                -- begin function "binary_to_lcd"                                function                                binary_to_lcd                                (                                -- list all input here                                signal                                switch                                :                                unsigned                                (                                3                                downto                                0                                )                                )                                -- only one value can be return                                return                                unsigned                                is                                variable                                lcdDisplay                                :                                unsigned                                (                                7                                downto                                0                                );                                begin                                case                                switch                                is                                when                                "0000"                                =>                                lcdDisplay                                :=                                "00110000"                                ;                                -- 0, active low i.e. 0:display & 1:no display                                when                                "0001"                                =>                                lcdDisplay                                :=                                "00110001"                                ;                                -- 1                                when                                "0010"                                =>                                lcdDisplay                                :=                                "00110010"                                ;                                -- 2                                when                                "0011"                                =>                                lcdDisplay                                :=                                "00110011"                                ;                                -- 3                                                                when                                "0100"                                =>                                lcdDisplay                                :=                                "00110100"                                ;                                -- 4                                when                                "0101"                                =>                                lcdDisplay                                :=                                "00110101"                                ;                                -- 5                                when                                "0110"                                =>                                lcdDisplay                                :=                                "00110110"                                ;                                -- 6                                when                                "0111"                                =>                                lcdDisplay                                :=                                "00110111"                                ;                                -- 7                                when                                "1000"                                =>                                lcdDisplay                                :=                                "00111000"                                ;                                -- 8                                when                                "1001"                                =>                                lcdDisplay                                :=                                "00111001"                                ;                                -- 9                                when                                "1010"                                =>                                lcdDisplay                                :=                                "01000001"                                ;                                -- a                                when                                "1011"                                =>                                lcdDisplay                                :=                                "01000010"                                ;                                -- b                                when                                "1100"                                =>                                lcdDisplay                                :=                                "01000011"                                ;                                -- c                                when                                "1101"                                =>                                lcdDisplay                                :=                                "01000100"                                ;                                -- d                                when                                "1110"                                =>                                lcdDisplay                                :=                                "01000101"                                ;                                -- e                                when                                others                                =>                                lcdDisplay                                :=                                "01000110"                                ;                                -- f                                end                                case                                ;                                return                                lcdDisplay                                ;                                end                                binary_to_lcd                                ;                                -- end function "binary_to_lcd"                                end                                LCD_SSD_display_pkg                                ;                              

Listing 11.19 LCD and seven-segment display

                                1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
                                                                -- LCD_SSD_display.vhd                                -- LCD and Seven-segment-display                                --------------------------------------------------                                -- ASCII HEX TABLE                                -- Hex Low Hex Digit                                -- Value 0  1 2 3 4 5 6 7 8 9 A B C D E F                                --------------------------------------------------                                --H 2 |  SP ! " # $ % & ' ( ) * + , - . /                                --i 3 |  0  1 2 3 4 5 6 7 8 9 : ; < = > ?                                --g 4 |  @  A B C D E F G H I J K L M N O                                --h 5 |  P  Q R S T U V W X Y Z [ \ ] ^ _                                --  6 |  `  a b c d e f g h i j k l m n o                                --  7 |  p  q r s t u v w x y z { | } ~ DEL                                --------------------------------------------------                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                use                                work.LCD_SSD_display_pkg.                                all                                ;                                entity                                LCD_SSD_display                                is                                generic                                (                                clk_dvd                                :                                natural                                :=                                500000                                ;                                max_count                                :                                natural                                :=                                16                                );                                port                                (                                CLOCK_50                                ,                                reset                                :                                in                                std_logic                                ;                                SW                                :                                in                                unsigned                                (                                3                                downto                                0                                );                                LEDG                                :                                out                                unsigned                                (                                3                                downto                                0                                );                                HEX0                                :                                out                                unsigned                                (                                6                                downto                                0                                );                                LCD_RS                                ,                                LCD_RW                                :                                out                                std_logic                                ;                                LCD_EN                                :                                out                                std_logic                                ;                                LCD_ON                                ,                                LCD_BLON                                :                                out                                std_logic                                ;                                -- LCD ON, Backlight ON                                LCD_DATA                                :                                out                                unsigned                                (                                7                                downto                                0                                )                                );                                end                                entity                                ;                                architecture                                arch                                of                                LCD_SSD_display                                is                                -- FSM for lcd display                                type                                stateType                                is                                (                                init1                                ,                                init2                                ,                                init3                                ,                                init4                                ,                                clearDisplay                                ,                                displayControl                                ,                                Line1                                ,                                Line2                                ,                                writeData_row1                                ,                                writeData_row2                                ,                                returnHome                                );                                signal                                state_reg                                ,                                state_next                                :                                stateType                                ;                                signal                                input_lcd                                :                                unsigned                                (                                7                                downto                                0                                );                                signal                                count                                :                                natural                                :=                                0                                ;                                signal                                char_count_reg                                ,                                char_count_next                                :                                natural                                :=                                0                                ;                                signal                                inc_count_reg                                ,                                inc_count_next                                :                                integer                                :=                                0                                ;                                signal                                lcd_clock                                :                                std_logic                                ;                                signal                                data1                                ,                                data2                                :                                unsigned                                (                                3                                downto                                0                                );                                type                                character_string                                is                                array                                (                                0                                to                                31                                )                                of                                unsigned                                (                                7                                downto                                0                                );                                signal                                LCD_display_string                                :                                character_string                                ;                                begin                                -- Data to be displayed :                                                                LCD_display_string                                <=                                (                                -- use spaces (X"20) for blank positions, then update these blank posistion                                                                -- with desired values e.g. in row 1 we udpated the blank position with switch value                                -- and in row 2, blank space is replaced by counting                                -- Line 1                                X"4D"                                ,                                X"45"                                ,                                X"48"                                ,                                X"45"                                ,                                X"52"                                ,                                X"20"                                ,                                X"20"                                ,                                X"53"                                ,                                -- -- MEHER  S                                X"57"                                ,                                X"20"                                ,                                X"3D"                                ,                                X"20"                                ,                                X"20"                                ,                                X"20"                                ,                                X"20"                                ,                                X"20"                                ,                                -- W =                                                                -- Line 2                                X"43"                                ,                                X"6F"                                ,                                X"75"                                ,                                X"6E"                                ,                                X"74"                                ,                                X"20"                                ,                                X"3D"                                ,                                X"20"                                ,                                -- count =                                                                X"20"                                ,                                X"20"                                ,                                X"20"                                ,                                X"20"                                ,                                X"20"                                ,                                X"20"                                ,                                X"20"                                ,                                X"20"                                -- 8 spaces                                                                );                                -- LED display                                LEDG                                <=                                SW                                ;                                -- seven-segment display                                HEX0                                <=                                binary_to_ssd                                (                                SW                                );                                -- lcd display                                LCD_ON                                <=                                '1'                                ;                                LCD_BLON                                <=                                '1'                                ;                                LCD_EN                                <=                                lcd_clock                                ;                                input_lcd                                <=                                binary_to_lcd                                (                                SW                                );                                -- clock divider which is used as "enable" signal for LCD                                -- this is required as for higher clock-rates, we can not see                                -- the data on the LCD.                                                                process                                (                                CLOCK_50                                ,                                reset                                )                                begin                                if                                reset                                =                                '1'                                then                                count                                <=                                0                                ;                                lcd_clock                                <=                                '0'                                ;                                elsif                                (                                rising_edge                                (                                CLOCK_50                                ))                                then                                count                                <=                                count                                +                                1                                ;                                if                                count                                =                                clk_dvd                                then                                lcd_clock                                <=                                not                                lcd_clock                                ;                                count                                <=                                0                                ;                                end                                if                                ;                                end                                if                                ;                                end                                process                                ;                                process                                (                                lcd_clock                                ,                                reset                                )                                begin                                if                                reset                                =                                '1'                                then                                state_reg                                <=                                init1                                ;                                inc_count_reg                                <=                                0                                ;                                char_count_reg                                <=                                0                                ;                                elsif                                (                                rising_edge                                (                                lcd_clock                                ))                                then                                state_reg                                <=                                state_next                                ;                                char_count_reg                                <=                                char_count_next                                ;                                inc_count_reg                                <=                                inc_count_next                                ;                                end                                if                                ;                                end                                process                                ;                                process                                (                                state_reg                                ,                                char_count_reg                                ,                                inc_count_reg                                ,                                data1                                ,                                data2                                ,                                LCD_display_string                                ,                                input_lcd                                )                                begin                                char_count_next                                <=                                char_count_reg                                ;                                inc_count_next                                <=                                inc_count_reg                                ;                                case                                state_reg                                is                                -- extra initialization states are required for proper reset operation                                when                                init1                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "00111000"                                ;                                -- change init2 to clearDisplay if extra-init is not required                                state_next                                <=                                init2                                ;                                when                                init2                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "00111000"                                ;                                state_next                                <=                                init3                                ;                                when                                init3                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "00111000"                                ;                                state_next                                <=                                init4                                ;                                when                                init4                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "00111000"                                ;                                state_next                                <=                                clearDisplay                                ;                                -- clear display and turn off cursor                                when                                clearDisplay                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "00000001"                                ;                                state_next                                <=                                displayControl                                ;                                -- turn on Display and turn off cursor                                when                                displayControl                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "00001100"                                ;                                state_next                                <=                                Line1                                ;                                -- Line 1                                -- write mode with auto-increment address and move cursor to the right                                when                                Line1                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "00000110"                                ;                                state_next                                <=                                writeData_row1                                ;                                -- write data                                                                when                                writeData_row1                                =>                                LCD_RS                                <=                                '1'                                ;                                LCD_RW                                <=                                '0'                                ;                                state_next                                <=                                writeData_row1                                ;                                char_count_next                                <=                                char_count_reg                                +                                1                                ;                                if                                char_count_reg                                =                                12                                then                                -- replace space at position 13 with number                                LCD_DATA                                <=                                input_lcd                                ;                                elsif                                char_count_reg                                <                                15                                then                                LCD_DATA                                <=                                LCD_display_string                                (                                char_count_reg                                );                                else                                -- char_count_reg = 15 then                                LCD_DATA                                <=                                LCD_display_string                                (                                char_count_reg                                );                                state_next                                <=                                Line2                                ;                                end                                if                                ;                                -- Line 2                                when                                Line2                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "11000000"                                ;                                state_next                                <=                                writeData_row2                                ;                                -- write data at line 2                                when                                writeData_row2                                =>                                LCD_RS                                <=                                '1'                                ;                                LCD_RW                                <=                                '0'                                ;                                state_next                                <=                                writeData_row2                                ;                                char_count_next                                <=                                char_count_reg                                +                                1                                ;                                if                                char_count_reg                                =                                24                                then                                -- replace space at location 26 with number                                -- decimal place of inc_count_reg                                data1                                <=                                unsigned                                (                                to_signed                                ((                                inc_count_reg                                /                                10                                )                                mod                                10                                ,                                4                                ));                                LCD_DATA                                <=                                binary_to_lcd                                (                                data1                                );                                elsif                                char_count_reg                                =                                25                                then                                -- unit place of inc_count_reg                                data2                                <=                                unsigned                                (                                to_signed                                (                                inc_count_reg                                mod                                10                                ,                                4                                ));                                LCD_DATA                                <=                                binary_to_lcd                                (                                data2                                );                                if                                inc_count_reg                                =                                max_count                                then                                -- reset if count reach to maximum                                inc_count_next                                <=                                0                                ;                                else                                inc_count_next                                <=                                inc_count_reg                                +                                1                                ;                                end                                if                                ;                                elsif                                char_count_reg                                <                                31                                then                                LCD_DATA                                <=                                LCD_display_string                                (                                char_count_reg                                );                                else                                -- char_count_reg = 31 then                                                                LCD_DATA                                <=                                LCD_display_string                                (                                char_count_reg                                );                                char_count_next                                <=                                0                                ;                                state_next                                <=                                returnHome                                ;                                end                                if                                ;                                -- Return write address to first character postion on line 1                                when                                returnHome                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "10000000"                                ;                                state_next                                <=                                writeData_row1                                ;                                end                                case                                ;                                end                                process                                ;                                end                                architecture                                ;                              

11.6.2. Example 2¶

In Listing 11.19, we used the the 'mod' and 'division' operation to display the integer values on the LCD. Note that, the division operation requires lots of hardware and for large integer values it can not be synthesized as well. Therefore it is better to display the number in 'Hexadecimal' format as shown in Listing 11.20. Note that, the binary format is not suitable as well, as it will need large number of characters to display the values on LCD.

Further, in Listing 11.20 the message format is defined, but the actual values are obtained from the Listing 11.21. In this way, we can separate the 'calculation' and 'displaying' designs, which is more manageable than previous case.

Listing 11.20 Message displayed on the LCD

                                1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
                                                                -- LCD_BER_display.vhd                                -- Message displayed on LCD and values are take from other entities                                --------------------------------------------------                                -- Message | Values (from other designs)                                -- Errors= | 0x03F                                -- Bits=   | 0x00000003F                                                                --------------------------------------------------                                -- ASCII HEX TABLE                                -- Hex Low Hex Digit                                -- Value 0  1 2 3 4 5 6 7 8 9 A B C D E F                                --------------------------------------------------                                --H 2 |  SP ! " # $ % & ' ( ) * + , - . /                                --i 3 |  0  1 2 3 4 5 6 7 8 9 : ; < = > ?                                --g 4 |  @  A B C D E F G H I J K L M N O                                --h 5 |  P  Q R S T U V W X Y Z [ \ ] ^ _                                --  6 |  `  a b c d e f g h i j k l m n o                                --  7 |  p  q r s t u v w x y z { | } ~ DEL                                --------------------------------------------------                                                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                use                                work.LCD_SSD_display_pkg.                                all                                ;                                entity                                LCD_BER_display                                is                                generic                                (                                -- dont go below 5000 as LCD will refresh very fast and we can see the values on LCD                                clk_dvd                                :                                natural                                :=                                50000                                ;                                max_count                                :                                natural                                :=                                16                                );                                port                                (                                CLOCK_50                                ,                                reset                                :                                in                                std_logic                                ;                                error_val                                :                                in                                unsigned                                (                                11                                downto                                0                                );                                total_bits                                :                                in                                unsigned                                (                                31                                downto                                0                                );                                LCD_RS                                ,                                LCD_RW                                :                                out                                std_logic                                ;                                LCD_EN                                :                                out                                std_logic                                ;                                LCD_ON                                ,                                LCD_BLON                                :                                out                                std_logic                                ;                                -- LCD ON, Backlight ON                                LCD_DATA                                :                                out                                unsigned                                (                                7                                downto                                0                                )                                );                                end                                entity                                ;                                architecture                                arch                                of                                LCD_BER_display                                is                                -- FSM for lcd display                                type                                stateType                                is                                (                                init1                                ,                                init2                                ,                                init3                                ,                                init4                                ,                                clearDisplay                                ,                                displayControl                                ,                                Line1                                ,                                Line2                                ,                                writeData_row1                                ,                                writeData_row2                                ,                                returnHome                                );                                signal                                state_reg                                ,                                state_next                                :                                stateType                                ;                                signal                                input_lcd                                :                                unsigned                                (                                7                                downto                                0                                );                                signal                                count                                :                                natural                                :=                                0                                ;                                signal                                char_count_reg                                ,                                char_count_next                                :                                natural                                :=                                0                                ;                                -- read the new input values after displaying the current values                                signal                                error_val_reg                                ,                                error_val_next                                :                                unsigned                                (                                11                                downto                                0                                );                                signal                                total_bits_reg                                ,                                total_bits_next                                :                                unsigned                                (                                31                                downto                                0                                );                                -- clock for LCD                                signal                                lcd_clock                                :                                std_logic                                ;                                -- 16X2 LCD : ASCII-format                                type                                character_string                                is                                array                                (                                0                                to                                31                                )                                of                                unsigned                                (                                7                                downto                                0                                );                                signal                                LCD_display_string                                :                                character_string                                ;                                begin                                -- Data to be displayed :                                                                LCD_display_string                                <=                                (                                -- use spaces (X"20) for blank positions, then update these blank posistion                                                                -- with desired values e.g. in row 1 we udpated the blank position with switch value                                -- and in row 2, blank space is replaced by counting                                -- Line 1                                X"45"                                ,                                X"72"                                ,                                X"72"                                ,                                X"6F"                                ,                                X"72"                                ,                                X"73"                                ,                                X"3D"                                ,                                X"20"                                ,                                -- Errors=                                                                X"30"                                ,                                X"78"                                ,                                X"20"                                ,                                X"20"                                ,                                X"20"                                ,                                X"20"                                ,                                X"20"                                ,                                X"20"                                ,                                -- 0x 6-spaces                                -- Line 2                                X"42"                                ,                                X"69"                                ,                                X"74"                                ,                                X"73"                                ,                                X"3D"                                ,                                X"20"                                ,                                X"30"                                ,                                X"78"                                ,                                -- Bits= 0x                                X"20"                                ,                                X"20"                                ,                                X"20"                                ,                                X"20"                                ,                                X"20"                                ,                                X"20"                                ,                                X"20"                                ,                                X"20"                                -- 8 spaces                                                                );                                -- lcd display settings                                LCD_ON                                <=                                '1'                                ;                                LCD_BLON                                <=                                '1'                                ;                                LCD_EN                                <=                                lcd_clock                                ;                                -- clock divider which is used as "enable" signal for LCD                                -- this is required as for higher clock-rates, we can not see                                -- the data on the LCD.                                                                process                                (                                CLOCK_50                                ,                                reset                                )                                begin                                if                                reset                                =                                '1'                                then                                count                                <=                                0                                ;                                lcd_clock                                <=                                '0'                                ;                                elsif                                (                                rising_edge                                (                                CLOCK_50                                ))                                then                                count                                <=                                count                                +                                1                                ;                                if                                count                                =                                clk_dvd                                then                                lcd_clock                                <=                                not                                lcd_clock                                ;                                count                                <=                                0                                ;                                end                                if                                ;                                end                                if                                ;                                end                                process                                ;                                -- current states for LCD data                                process                                (                                lcd_clock                                ,                                reset                                )                                begin                                if                                reset                                =                                '1'                                then                                state_reg                                <=                                init1                                ;                                char_count_reg                                <=                                0                                ;                                total_bits_reg                                <=                                (                                others                                =>                                '0'                                );                                error_val_reg                                <=                                (                                others                                =>                                '0'                                );                                elsif                                (                                rising_edge                                (                                lcd_clock                                ))                                then                                state_reg                                <=                                state_next                                ;                                char_count_reg                                <=                                char_count_next                                ;                                total_bits_reg                                <=                                total_bits_next                                ;                                error_val_reg                                <=                                error_val_next                                ;                                end                                if                                ;                                end                                process                                ;                                -- write data on LCD and calculate next-states of LCD                                process                                (                                state_reg                                ,                                char_count_reg                                ,                                error_val_reg                                ,                                LCD_display_string                                ,                                error_val                                ,                                total_bits                                ,                                total_bits_reg                                ,                                input_lcd                                )                                begin                                char_count_next                                <=                                char_count_reg                                ;                                total_bits_next                                <=                                total_bits_reg                                ;                                error_val_next                                <=                                error_val_reg                                ;                                case                                state_reg                                is                                -- extra initialization states are required for proper reset operation                                when                                init1                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "00111000"                                ;                                -- change init2 to clearDisplay if extra-init is not required                                state_next                                <=                                init2                                ;                                when                                init2                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "00111000"                                ;                                state_next                                <=                                init3                                ;                                when                                init3                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "00111000"                                ;                                state_next                                <=                                init4                                ;                                when                                init4                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "00111000"                                ;                                state_next                                <=                                clearDisplay                                ;                                -- clear display and turn off cursor                                when                                clearDisplay                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "00000001"                                ;                                state_next                                <=                                displayControl                                ;                                -- turn on Display and turn off cursor                                when                                displayControl                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "00001100"                                ;                                state_next                                <=                                Line1                                ;                                -- Line 1                                -- write mode with auto-increment address and move cursor to the right                                when                                Line1                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "00000110"                                ;                                state_next                                <=                                writeData_row1                                ;                                -- write data                                                                when                                writeData_row1                                =>                                LCD_RS                                <=                                '1'                                ;                                LCD_RW                                <=                                '0'                                ;                                state_next                                <=                                writeData_row1                                ;                                char_count_next                                <=                                char_count_reg                                +                                1                                ;                                if                                char_count_reg                                =                                10                                then                                -- replace space at position 13 with number                                LCD_DATA                                <=                                binary_to_lcd                                (                                error_val_reg                                (                                11                                downto                                8                                ));                                elsif                                char_count_reg                                =                                11                                then                                LCD_DATA                                <=                                binary_to_lcd                                (                                error_val_reg                                (                                7                                downto                                4                                ));                                elsif                                char_count_reg                                =                                12                                then                                LCD_DATA                                <=                                binary_to_lcd                                (                                error_val_reg                                (                                3                                downto                                0                                ));                                elsif                                char_count_reg                                <                                15                                then                                LCD_DATA                                <=                                LCD_display_string                                (                                char_count_reg                                );                                else                                -- char_count_reg = 15 then                                LCD_DATA                                <=                                LCD_display_string                                (                                char_count_reg                                );                                state_next                                <=                                Line2                                ;                                end                                if                                ;                                -- Line 2                                when                                Line2                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "11000000"                                ;                                state_next                                <=                                writeData_row2                                ;                                -- write data at line 2                                when                                writeData_row2                                =>                                LCD_RS                                <=                                '1'                                ;                                LCD_RW                                <=                                '0'                                ;                                state_next                                <=                                writeData_row2                                ;                                char_count_next                                <=                                char_count_reg                                +                                1                                ;                                if                                char_count_reg                                =                                24                                then                                -- replace space at position 13 with number                                LCD_DATA                                <=                                binary_to_lcd                                (                                total_bits_reg                                (                                31                                downto                                28                                ));                                elsif                                char_count_reg                                =                                25                                then                                LCD_DATA                                <=                                binary_to_lcd                                (                                total_bits_reg                                (                                27                                downto                                24                                ));                                elsif                                char_count_reg                                =                                26                                then                                LCD_DATA                                <=                                binary_to_lcd                                (                                total_bits_reg                                (                                23                                downto                                20                                ));                                elsif                                char_count_reg                                =                                27                                then                                LCD_DATA                                <=                                binary_to_lcd                                (                                total_bits_reg                                (                                19                                downto                                16                                ));                                elsif                                char_count_reg                                =                                28                                then                                LCD_DATA                                <=                                binary_to_lcd                                (                                total_bits_reg                                (                                15                                downto                                12                                ));                                elsif                                char_count_reg                                =                                29                                then                                LCD_DATA                                <=                                binary_to_lcd                                (                                total_bits_reg                                (                                11                                downto                                8                                ));                                elsif                                char_count_reg                                =                                30                                then                                LCD_DATA                                <=                                binary_to_lcd                                (                                total_bits_reg                                (                                7                                downto                                4                                ));                                elsif                                char_count_reg                                =                                31                                then                                -- reached to end, hence go to "returnHome"                                LCD_DATA                                <=                                binary_to_lcd                                (                                total_bits_reg                                (                                3                                downto                                0                                ));                                state_next                                <=                                returnHome                                ;                                char_count_next                                <=                                0                                ;                                else                                LCD_DATA                                <=                                LCD_display_string                                (                                char_count_reg                                );                                end                                if                                ;                                -- Return write address to first character postion on line 1                                when                                returnHome                                =>                                LCD_RS                                <=                                '0'                                ;                                LCD_RW                                <=                                '0'                                ;                                LCD_DATA                                <=                                "10000000"                                ;                                state_next                                <=                                writeData_row1                                ;                                error_val_next                                <=                                error_val                                ;                                total_bits_next                                <=                                total_bits                                ;                                end                                case                                ;                                end                                process                                ;                                end                                architecture                                ;                              

Listing 11.21 Top level entity which provides the values to Listing 11.20

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
                                                                -- LCD_BER_display_top.vhd                                -- test the LCD display                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                use                                work.LCD_SSD_display_pkg.                                all                                ;                                entity                                LCD_BER_display_top                                is                                generic                                (                                -- dont go below 5000 as LCD will refresh very fast and we can see the values on LCD                                clk_dvd                                :                                natural                                :=                                50000                                ;                                max_count                                :                                natural                                :=                                16                                );                                port                                (                                CLOCK_50                                ,                                reset                                :                                in                                std_logic                                ;                                SW                                :                                in                                unsigned                                (                                11                                downto                                0                                );                                LCD_RS                                ,                                LCD_RW                                :                                out                                std_logic                                ;                                LCD_EN                                :                                out                                std_logic                                ;                                LCD_ON                                ,                                LCD_BLON                                :                                out                                std_logic                                ;                                -- LCD ON, Backlight ON                                LCD_DATA                                :                                out                                unsigned                                (                                7                                downto                                0                                )                                );                                end                                entity                                ;                                architecture                                arch                                of                                LCD_BER_display_top                                is                                begin                                unit_LCD_BER                                :                                entity                                work                                .                                LCD_BER_display                                port                                map                                (                                CLOCK_50                                =>                                CLOCK_50                                ,                                reset                                =>                                reset                                ,                                -- convert 6 bits to 12 and 32 bits format                                error_val                                =>                                to_unsigned                                (                                to_integer                                (                                SW                                (                                5                                downto                                0                                )),                                12                                ),                                total_bits                                =>                                to_unsigned                                (                                to_integer                                (                                SW                                (                                11                                downto                                6                                )),                                32                                ),                                -- LCD control                                LCD_RS                                =>                                LCD_RS                                ,                                LCD_RW                                =>                                LCD_RW                                ,                                LCD_EN                                =>                                LCD_EN                                ,                                LCD_ON                                =>                                LCD_ON                                ,                                LCD_BLON                                =>                                LCD_BLON                                ,                                LCD_DATA                                =>                                LCD_DATA                                );                                end                                architecture                                ;                              

11.6.3. Example 3 : Error counting¶

In Listing 11.21, we if we change the position of the switches, then corresponding values are shown in the LCD display. In this section, we will use two switches where one switch will act as transmitted signal and second switch will act as detected signal. If the two values are different, then error-count and transmitted-bit-count will increase; but if both the values are same then only bit-count will increase (and error-count will remain constant as there is not error).

For this, first we need to design a error-count circuit as shown in Listing 11.23. Next, we integrated Listing 11.23 and Listing 11.19 in one listing i.e. Listing 11.24; this is done so that we need to instantiate only one design to count and display the errors. In the other words, the main design should send the transmitted and detected bit patterns to Listing 11.24 and the rest of the job, i.e. error calculation and error display, will be performed by the Listing 11.24, as discussed in next paragraph.

Finally a top level design is created in Listing 11.22, which sends the transmitted and detected bit patterns (using SW) to the Listing 11.24. If both switches are at the same position then only transmitted-bit-count will increase, otherwise both error-count and transmitted-bit-count will increase. And the counting will stop when the maximum number of errors will be reached.

Note

  • Different clock-rates are used for LCD-display and error-calculation, as both the design needs different frequency of operations, as shown in top level design for the error counter (see Lines 58 and 61 of Listing 11.22).
  • The 'reset_n' is used in the design which is (KEY(3)) on the DE2 board. This is also important because the SW switches of the DE2 board are not implemented with debouncing circuits, therefore if the error calculation are performed on high clock rate (in actual system, not in the current design), then 200 errors will be detected on the reset operation itself.
  • Further, error calculations is skipped for first few clocks as shown in Lines 67-76 of Listing 11.23. During these cycles, '0xFFF…' are displayed on the screen. Please, read the comments for more details.
  • Lastly is better to use 'KEY (i.e. reset_n)' for reset operations at the top level design only; because by default 'KEY' is set to high position, therefore 'not' operation is required as shown in Line 28 of Listing 11.22. If we use 'reset_n' then it will create lots of confusion, as not operation is used with it for resetting the system.

Listing 11.22 Top level design which sends the transmitted and detected bit pattern

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
                                                                -- error_lcd_connection_test_v1.vhd                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                entity                                error_lcd_connection_test_v1                                is                                generic                                (                                -- total number of errors                                num_of_errors                                :                                unsigned                                (                                11                                downto                                0                                )                                :=                                to_unsigned                                (                                100                                ,                                12                                )                                );                                port                                (                                CLOCK_50                                ,                                reset_n                                :                                in                                std_logic                                ;                                SW                                :                                in                                std_logic_vector                                (                                1                                downto                                0                                );                                -- 1 tx bit, 0 detected bit                                                                LCD_RS                                ,                                LCD_RW                                :                                out                                std_logic                                ;                                LCD_EN                                :                                out                                std_logic                                ;                                LCD_ON                                ,                                LCD_BLON                                :                                out                                std_logic                                ;                                -- LCD ON, Backlight ON                                LCD_DATA                                :                                out                                unsigned                                (                                7                                downto                                0                                )                                );                                end                                entity                                ;                                architecture                                arch                                of                                error_lcd_connection_test_v1                                is                                signal                                total_errors_reg                                :                                unsigned                                (                                11                                downto                                0                                );                                signal                                total_bits_reg                                :                                unsigned                                (                                31                                downto                                0                                );                                signal                                clk_error                                ,                                clk_LCD                                ,                                reset                                :                                std_logic                                ;                                begin                                reset                                <=                                not                                reset_n                                ;                                unit_error_counter                                :                                entity                                work                                .                                error_lcd_connection_v1                                generic                                map                                (                                num_of_errors                                =>                                num_of_errors                                )                                port                                map                                (                                clk_error                                =>                                clk_error                                ,                                clk_LCD                                =>                                clk_LCD                                ,                                reset                                =>                                reset                                ,                                tx_bit                                =>                                SW                                (                                1                                ),                                detected_bit                                =>                                SW                                (                                0                                ),                                -- LCD control                                LCD_RS                                =>                                LCD_RS                                ,                                LCD_RW                                =>                                LCD_RW                                ,                                LCD_EN                                =>                                LCD_EN                                ,                                LCD_ON                                =>                                LCD_ON                                ,                                LCD_BLON                                =>                                LCD_BLON                                ,                                LCD_DATA                                =>                                LCD_DATA                                );                                -- 1 ms clock                                unit_clockTick                                :                                entity                                work                                .                                clockTick                                generic                                map                                (                                M                                =>                                5000000                                ,                                N                                =>                                26                                )                                port                                map                                (                                clk                                =>                                CLOCK_50                                ,                                reset                                =>                                reset                                ,                                clkPulse                                =>                                clk_error                                -- clk_error                                );                                clk_LCD                                <=                                CLOCK_50                                ;                                -- clk_LCD                                end                                arch                                ;                              

Listing 11.23 Error counter

                                1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100
                                                                -- error_counter_v1.vhd                                -- version : 1                                -- Meher Krishna Patel                                -- Date : 21-Sep-2017                                -- counts the pre-defined number of errors and and                                                                -- number of bits transmitted for the total number of errors                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                entity                                error_counter_v1                                is                                generic                                (                                -- total number of errors                                num_of_errors                                :                                unsigned                                (                                11                                downto                                0                                )                                :=                                to_unsigned                                (                                50                                ,                                12                                );                                -- 6000 for SF = 50; 500 for SF = 100                                skip_clock                                :                                unsigned                                (                                15                                downto                                0                                )                                :=                                to_unsigned                                (                                500                                ,                                16                                )                                );                                port                                (                                clk                                ,                                reset                                :                                in                                std_logic                                ;                                tx_bit                                ,                                detected_bit                                :                                in                                std_logic                                ;                                total_errors                                :                                out                                unsigned                                (                                11                                downto                                0                                );                                total_bits                                :                                out                                unsigned                                (                                31                                downto                                0                                )                                );                                end                                entity                                ;                                architecture                                arch                                of                                error_counter_v1                                is                                signal                                count_errors                                ,                                count_errors_next                                :                                unsigned                                (                                11                                downto                                0                                )                                :=                                (                                others                                =>                                '0'                                );                                signal                                count_bits                                ,                                count_bits_next                                :                                unsigned                                (                                31                                downto                                0                                )                                :=                                (                                others                                =>                                '0'                                );                                -- skip first few clocks, so that reset signal settle down,                                                                -- it is required for proper BER display on the LCD, otherwise                                                                -- error will be calculated while reset is settling down                                                                -- This happens becuase, we are manually reseting the system.                                                                -- if require, increase/decrease the value of "count_skip_errors"                                signal                                count_skip_errors                                :                                unsigned                                (                                31                                downto                                0                                )                                :=                                to_unsigned                                (                                20                                ,                                32                                );                                signal                                count_skip_reg                                ,                                count_skip_next                                :                                unsigned                                (                                32                                downto                                0                                );                                type                                stateType                                is                                (                                setup                                ,                                start                                );                                --, done);                                signal                                state_reg                                ,                                state_next                                :                                stateType                                ;                                begin                                process                                (                                clk                                ,                                reset                                )                                begin                                if                                reset                                =                                '1'                                then                                count_bits                                <=                                (                                others                                =>                                '0'                                );                                count_errors                                <=                                (                                others                                =>                                '0'                                );                                count_skip_reg                                <=                                (                                others                                =>                                '0'                                );                                state_reg                                <=                                setup                                ;                                elsif                                falling_edge                                (                                clk                                )                                then                                count_bits                                <=                                count_bits_next                                ;                                count_errors                                <=                                count_errors_next                                ;                                count_skip_reg                                <=                                count_skip_next                                ;                                state_reg                                <=                                state_next                                ;                                end                                if                                ;                                end                                process                                ;                                process                                (                                tx_bit                                ,                                detected_bit                                ,                                count_errors                                ,                                count_bits                                ,                                state_reg                                ,                                count_skip_reg                                ,                                count_skip_errors                                )                                begin                                count_bits_next                                <=                                count_bits                                ;                                count_errors_next                                <=                                count_errors                                ;                                count_skip_next                                <=                                count_skip_reg                                ;                                state_next                                <=                                state_reg                                ;                                case                                state_reg                                is                                when                                setup                                =>                                -- do not count error for first few cycles                                if                                (                                count_skip_reg                                /=                                count_skip_errors                                )                                then                                count_bits_next                                <=                                (                                others                                =>                                '1'                                );                                -- display 0xFFF                                count_errors_next                                <=                                (                                others                                =>                                '1'                                );                                -- display 0xFFFFFFFF                                count_skip_next                                <=                                count_skip_reg                                +                                1                                ;                                elsif                                count_skip_reg                                =                                count_skip_errors                                then                                count_errors_next                                <=                                (                                others                                =>                                '0'                                );                                count_bits_next                                <=                                (                                others                                =>                                '0'                                );                                state_next                                <=                                start                                ;                                end                                if                                ;                                when                                start                                =>                                -- start counting-errors                                if                                (                                count_errors                                /=                                num_of_errors                                )                                then                                if                                tx_bit                                /=                                detected_bit                                then                                count_bits_next                                <=                                count_bits                                +                                1                                ;                                -- increment values                                count_errors_next                                <=                                count_errors                                +                                1                                ;                                elsif                                tx_bit                                =                                detected_bit                                then                                count_bits_next                                <=                                count_bits                                +                                1                                ;                                count_errors_next                                <=                                count_errors                                ;                                end                                if                                ;                                elsif                                count_errors                                =                                num_of_errors                                then                                -- if maximum error reached                                count_bits_next                                <=                                count_bits                                ;                                -- then stop incrementing values                                count_errors_next                                <=                                count_errors                                ;                                end                                if                                ;                                end                                case                                ;                                end                                process                                ;                                -- assign values to output ports                                total_errors                                <=                                count_errors                                ;                                total_bits                                <=                                count_bits                                ;                                end                                arch                                ;                              

Listing 11.24 Connect error-counting and LCD-display in one design

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
                                                                -- error_lcd_connection_v1.vhd                                -- version : 1                                -- Meher Krishna Patel                                -- Date : 21-Sep-2017                                -- connects the error_counter_v1.vhd and LCD_BER_display.vhd to display                                -- BER on the LCD                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                entity                                error_lcd_connection_v1                                is                                generic                                (                                -- total number of errors                                num_of_errors                                :                                unsigned                                (                                11                                downto                                0                                )                                :=                                to_unsigned                                (                                200                                ,                                12                                )                                );                                port                                (                                clk_error                                ,                                clk_LCD                                ,                                reset                                :                                in                                std_logic                                ;                                tx_bit                                ,                                detected_bit                                :                                in                                std_logic                                ;                                --total_errors : out unsigned(11 downto 0);                                --total_bits : out unsigned(31 downto 0);                                LCD_RS                                ,                                LCD_RW                                :                                out                                std_logic                                ;                                LCD_EN                                :                                out                                std_logic                                ;                                LCD_ON                                ,                                LCD_BLON                                :                                out                                std_logic                                ;                                -- LCD ON, Backlight ON                                LCD_DATA                                :                                out                                unsigned                                (                                7                                downto                                0                                )                                );                                end                                entity                                ;                                architecture                                arch                                of                                error_lcd_connection_v1                                is                                signal                                total_errors_reg                                :                                unsigned                                (                                11                                downto                                0                                );                                signal                                total_bits_reg                                :                                unsigned                                (                                31                                downto                                0                                );                                begin                                unit_error_counter                                :                                entity                                work                                .                                error_counter_v1                                generic                                map                                (                                num_of_errors                                =>                                num_of_errors                                )                                port                                map                                (                                clk                                =>                                clk_error                                ,                                reset                                =>                                reset                                ,                                tx_bit                                =>                                tx_bit                                ,                                detected_bit                                =>                                detected_bit                                ,                                total_errors                                =>                                total_errors_reg                                ,                                total_bits                                =>                                total_bits_reg                                );                                unit_LCD_BER                                :                                entity                                work                                .                                LCD_BER_display                                port                                map                                (                                CLOCK_50                                =>                                clk_LCD                                ,                                reset                                =>                                reset                                ,                                -- convert 6 bits to 12 and 32 bits format                                error_val                                =>                                total_errors_reg                                ,                                total_bits                                =>                                total_bits_reg                                ,                                -- LCD control                                LCD_RS                                =>                                LCD_RS                                ,                                LCD_RW                                =>                                LCD_RW                                ,                                LCD_EN                                =>                                LCD_EN                                ,                                LCD_ON                                =>                                LCD_ON                                ,                                LCD_BLON                                =>                                LCD_BLON                                ,                                LCD_DATA                                =>                                LCD_DATA                                );                                end                                arch                                ;                              

11.7. VGA interface¶

In this section, VGA interface is crated for FPGA devices. VHDL files required for this example are listed below,

  • sync_VGA.vhd
  • sync_VGA_visualTest.vhd
  • sync_VGA_visualTest2.vhd
  • clockTick.vhd
  • modMCounter.vhd

Note that, 'clockTick.vhd' and 'modMCounter.vhd' are discussed in Chapter 8.

11.7.1. Synchronization circuit¶

To display the data generated from FPGA on the VGA screen, we need to send synchronization signal along with some other signals e.g. horizontal synchronization signal, vertical synchronization signals and 25 MHz VGA clock etc. Listing 11.25 generates a synchronization circuit to display the data on the VGA screen.

Listing 11.25 VGA synchronization circuit

                                1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
                                                                -- sync_VGA_visualTest.vhd                                -- created by  :  Meher Krishna Patel                                -- date        :  24-Dec-16                                -- Functionality:                                -- synchronize the VGA system                                -- ports:                                -- vga_clk : 25 MHz clock for VGA operation (generated by sync_VGA.vhd file)                                -- video_on : send video_on = '0' while synchronization ohtherwise '1' to display data                                -- hsync and vsync : synchronization signals required for VGA operation                                -- pixel_x and pixel_y : 10 bit pixel location                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                entity                                sync_VGA                                is                                port                                (                                clk                                ,                                reset                                :                                in                                std_logic                                ;                                hsync                                ,                                vsync                                :                                out                                std_logic                                ;                                video_on                                ,                                vga_clk                                :                                out                                std_logic                                ;                                pixel_x                                ,                                pixel_y                                :                                out                                std_logic_vector                                (                                9                                downto                                0                                )                                );                                end                                sync_VGA                                ;                                architecture                                arch                                of                                sync_VGA                                is                                -- VGA 640-by-480                                                                constant                                HD                                :                                integer                                :=                                640                                ;                                -- horizontal display area                                constant                                VD                                :                                integer                                :=                                480                                ;                                -- vertical display area                                -- Horizontal and Vertical retraces                                constant                                HR                                :                                integer                                :=                                100                                ;                                -- horizontal retrace                                constant                                VR                                :                                integer                                :=                                10                                ;                                -- vertical retrace                                -- 25 MHz VGA clock                                                                signal                                vga_tick                                :                                std_logic                                ;                                -- pixel location                                signal                                h_pixel                                ,                                h_pixel_next                                :                                unsigned                                (                                9                                downto                                0                                );                                signal                                v_pixel                                ,                                v_pixel_next                                :                                unsigned                                (                                9                                downto                                0                                );                                -- store location of screen-ends for retracing operation                                signal                                h_end                                ,                                v_end                                :                                std_logic                                ;                                begin                                -- 25 MHz clock for VGA operations                                clock_25MHz                                :                                entity                                work                                .                                clockTick                                generic                                map                                (                                M                                =>                                2                                ,                                N                                =>                                2                                )                                port                                map                                (                                clk                                =>                                clk                                ,                                reset                                =>                                reset                                ,                                clkPulse                                =>                                vga_tick                                );                                -- reset pixel location                                process                                (                                clk                                ,                                reset                                )                                begin                                if                                reset                                =                                '1'                                then                                v_pixel                                <=                                (                                others                                =>                                '0'                                );                                h_pixel                                <=                                (                                others                                =>                                '0'                                );                                elsif                                (                                clk                                'event                                and                                clk                                =                                '1'                                )                                then                                v_pixel                                <=                                v_pixel_next                                ;                                h_pixel                                <=                                h_pixel_next                                ;                                end                                if                                ;                                end                                process                                ;                                -- video on/off                                process                                (                                clk                                ,                                h_pixel                                ,                                v_pixel                                )                                begin                                if                                (                                h_pixel                                <                                HD                                and                                v_pixel                                <                                VD                                )                                then                                video_on                                <=                                '1'                                ;                                else                                video_on                                <=                                '0'                                ;                                end                                if                                ;                                end                                process                                ;                                -- end points for retrace                                h_end                                <=                                '1'                                when                                h_pixel                                =                                (                                HD                                +                                HR                                -                                1                                )                                else                                '0'                                ;                                v_end                                <=                                '1'                                when                                v_pixel                                =                                (                                VD                                +                                VR                                -                                1                                )                                else                                '0'                                ;                                -- set h_pixel_next to zero when end of horizontal-screen reached                                -- otherwise increment on vga_tick                                process                                (                                vga_tick                                ,                                h_pixel                                ,                                h_end                                )                                begin                                if                                vga_tick                                =                                '1'                                then                                if                                h_end                                =                                '1'                                then                                h_pixel_next                                <=                                (                                others                                =>                                '0'                                );                                else                                h_pixel_next                                <=                                h_pixel                                +                                1                                ;                                end                                if                                ;                                else                                h_pixel_next                                <=                                h_pixel                                ;                                end                                if                                ;                                end                                process                                ;                                -- set v_pixel_next to zero when end of horizontal and vertical screen reached                                -- otherwise increment on vga_tick                                process                                (                                vga_tick                                ,                                v_pixel                                ,                                h_end                                ,                                v_end                                )                                begin                                if                                vga_tick                                =                                '1'                                and                                h_end                                =                                '1'                                then                                if                                (                                v_end                                =                                '1'                                )                                then                                v_pixel_next                                <=                                (                                others                                =>                                '0'                                );                                else                                v_pixel_next                                <=                                v_pixel                                +                                1                                ;                                end                                if                                ;                                else                                v_pixel_next                                <=                                v_pixel                                ;                                end                                if                                ;                                end                                process                                ;                                -- horizontal and vertical sync signals                                hsync                                <=                                '1'                                when                                (                                h_pixel                                >=                                (                                HD                                ))                                and                                (                                h_pixel                                <=                                (                                HD                                +                                HR                                -                                1                                ))                                else                                '0'                                ;                                vsync                                <=                                '1'                                when                                (                                v_pixel                                >=                                (                                VD                                ))                                and                                (                                v_pixel                                <=                                (                                VD                                +                                VR                                -                                1                                ))                                else                                '0'                                ;                                -- convert unsigned-pixel-locations to std_logic_vector format                                pixel_x                                <=                                std_logic_vector                                (                                h_pixel                                );                                pixel_y                                <=                                std_logic_vector                                (                                v_pixel                                );                                -- send clock to output port                                vga_clk                                <=                                vga_tick                                ;                                end                                arch                                ;                              

11.7.2. Visual test : change screen color with switches¶

Listing 11.26 can be used to test Listing 11.25. The color of the screen will be change according to combination of switches.

Listing 11.26 Change screen color with switches

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
                                                                -- sync_VGA_visualTest.vhd                                -- created by  :  Meher Krishna Patel                                -- date        :  24-Dec-16                                -- Functionality:                                -- change the color of screen based on switch combination i.e. 0 to 7                                -- ports:                                -- VGA_CLK : 25 MHz clock for VGA operation (generated by sync_VGA.vhd file)                                -- VGA_BLANK : required for VGA operations and set to 1                                -- SW : combination will change the color of screen                                -- VGA_HS and VGA_VS : synchronization signals required for VGA operation                                -- VGA_R, VGA_G and VGA_B : 10 bit RGB signals for displaying colors on screen                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                entity                                sync_VGA_visualTest                                is                                port                                (                                CLOCK_50                                ,                                reset                                :                                in                                std_logic                                ;                                VGA_CLK                                ,                                VGA_BLANK                                :                                out                                std_logic                                ;                                SW                                :                                in                                std_logic_vector                                (                                2                                downto                                0                                );                                VGA_HS                                ,                                VGA_VS                                :                                out                                std_logic                                ;                                VGA_R                                ,                                VGA_G                                ,                                VGA_B                                :                                out                                std_logic_vector                                (                                9                                downto                                0                                )                                );                                end                                sync_VGA_visualTest                                ;                                architecture                                arch                                of                                sync_VGA_visualTest                                is                                signal                                rgb_reg                                :                                std_logic_vector                                (                                2                                downto                                0                                );                                signal                                video_on                                :                                std_logic                                ;                                begin                                -- set VGA_BLANK to 1                                VGA_BLANK                                <=                                '1'                                ;                                -- instantiate sync_VGA for synchronization                                                                sync_VGA_unit                                :                                entity                                work                                .                                sync_VGA                                port                                map                                (                                clk                                =>                                CLOCK_50                                ,                                reset                                =>                                reset                                ,                                hsync                                =>                                VGA_HS                                ,                                vsync                                =>                                VGA_VS                                ,                                video_on                                =>                                video_on                                ,                                vga_clk                                =>                                VGA_CLK                                ,                                pixel_x                                =>                                open                                );                                -- read switch and store in rgb_reg                                process                                (                                CLOCK_50                                ,                                reset                                )                                begin                                if                                reset                                =                                '1'                                then                                rgb_reg                                <=                                (                                others                                =>                                '0'                                );                                elsif                                (                                CLOCK_50                                'event                                and                                CLOCK_50                                =                                '1'                                )                                then                                rgb_reg                                <=                                SW                                ;                                end                                if                                ;                                end                                process                                ;                                -- send MSB of rgb_reg to all the 10 bits of VGA_R                                -- repeat it for VGA_G and VGA_B with rgb_reg(1) and rgb_reg(0) respectively                                VGA_R                                <=                                (                                others                                =>                                rgb_reg                                (                                2                                ))                                when                                video_on                                =                                '1'                                else                                (                                others                                =>                                '0'                                );                                VGA_G                                <=                                (                                others                                =>                                rgb_reg                                (                                1                                ))                                when                                video_on                                =                                '1'                                else                                (                                others                                =>                                '0'                                );                                VGA_B                                <=                                (                                others                                =>                                rgb_reg                                (                                0                                ))                                when                                video_on                                =                                '1'                                else                                (                                others                                =>                                '0'                                );                                end                                arch                                ;                              

11.7.3. Visual test : display different colors on screen¶

Listing 11.27 displays four different colors on the screen as shown in Fig. 11.13.

../_images/sync_VGA_visualTest2.jpg

Fig. 11.13 Screen with four different colors (Listing 11.27)

Listing 11.27 Display different colors on screen

                                1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
                                                                -- sync_VGA_visualTest2.vhd                                -- created by   :   Meher Krishna Patel                                -- date         :   27-Dec-16                                -- Functionality:                                -- display four squares of different colors on the screen                                -- ports:                                -- VGA_CLK : 25 MHz clock for VGA operation (generated by sync_VGA.vhd file)                                -- VGA_BLANK : required for VGA operations and set to 1                                -- VGA_HS and VGA_VS : synchronization signals required for VGA operation                                -- VGA_R, VGA_G and VGA_B : 10 bit RGB signals for displaying colors on screen                                library                                ieee                                ;                                use                                ieee.std_logic_1164.                                all                                ;                                use                                ieee.numeric_std.                                all                                ;                                entity                                sync_VGA_visualTest2                                is                                port                                (                                CLOCK_50                                ,                                reset                                :                                in                                std_logic                                ;                                VGA_CLK                                ,                                VGA_BLANK                                :                                out                                std_logic                                ;                                VGA_HS                                ,                                VGA_VS                                :                                out                                std_logic                                ;                                VGA_R                                ,                                VGA_G                                ,                                VGA_B                                :                                out                                std_logic_vector                                (                                9                                downto                                0                                )                                );                                end                                sync_VGA_visualTest2                                ;                                architecture                                arch                                of                                sync_VGA_visualTest2                                is                                signal                                rgb_reg                                :                                std_logic_vector                                (                                2                                downto                                0                                );                                signal                                video_on                                :                                std_logic                                ;                                signal                                pixel_x                                ,                                pixel_y                                :                                std_logic_vector                                (                                9                                downto                                0                                );                                signal                                pix_x                                ,                                pix_y                                :                                integer                                ;                                begin                                -- set VGA_BLANK to 1                                VGA_BLANK                                <=                                '1'                                ;                                -- instantiate sync_VGA for synchronization                                                                sync_VGA_unit                                :                                entity                                work                                .                                sync_VGA                                port                                map                                (                                clk                                =>                                CLOCK_50                                ,                                reset                                =>                                reset                                ,                                hsync                                =>                                VGA_HS                                ,                                vsync                                =>                                VGA_VS                                ,                                video_on                                =>                                video_on                                ,                                vga_clk                                =>                                VGA_CLK                                ,                                pixel_x                                =>                                pixel_x                                ,                                pixel_y                                =>                                pixel_y                                );                                pix_x                                <=                                to_integer                                (                                unsigned                                (                                pixel_x                                ));                                pix_y                                <=                                to_integer                                (                                unsigned                                (                                pixel_y                                ));                                process                                (                                CLOCK_50                                )                                begin                                if                                (                                video_on                                =                                '1'                                )                                then                                -- divide VGA screen i.e. 640-by-480 in four equal parts                                -- and display different colors in those parts                                -- Red color                                if                                (                                pix_x                                <                                320                                and                                pix_y                                <                                240                                )                                then                                -- 640/2 = 320 and 480/2 = 240                                VGA_R                                <=                                (                                others                                =>                                '1'                                );                                -- send '1' to all 10 bits of VGA_R                                VGA_G                                <=                                (                                others                                =>                                '0'                                );                                VGA_B                                <=                                (                                others                                =>                                '0'                                );                                -- Green color                                elsif                                (                                pix_x                                >=                                320                                and                                pix_y                                <                                240                                )                                then                                VGA_R                                <=                                (                                others                                =>                                '0'                                );                                VGA_G                                <=                                (                                others                                =>                                '1'                                );                                VGA_B                                <=                                (                                others                                =>                                '0'                                );                                -- Blue color                                elsif                                (                                pix_x                                <                                320                                and                                pix_y                                >=                                240                                )                                then                                VGA_R                                <=                                (                                others                                =>                                '0'                                );                                VGA_G                                <=                                (                                others                                =>                                '0'                                );                                VGA_B                                <=                                (                                others                                =>                                '1'                                );                                -- Yellow color                                else                                VGA_R                                <=                                (                                others                                =>                                '1'                                );                                VGA_G                                <=                                (                                others                                =>                                '1'                                );                                VGA_B                                <=                                (                                others                                =>                                '0'                                );                                end                                if                                ;                                else                                VGA_R                                <=                                (                                others                                =>                                '0'                                );                                VGA_G                                <=                                (                                others                                =>                                '0'                                );                                VGA_B                                <=                                (                                others                                =>                                '0'                                );                                end                                if                                ;                                end                                process                                ;                                end                                arch                                ;