Start Research Competences Projects Publications
Optical Systems
Optics
TOF
FPGA
Deutsch
Print version
PDF
LDCON
CNC
Optical Systems using FPGAs

Overview

Basics


Digital components and techniques play an incerasing role in optical science and optical instruments. One main area is digital image processing for image analysis and manipulation of image data. Beneath this well known area digital logic is used for control purposes, too. One solution for digital control is the use of microcontrollers which execute an algorithm in sequentiel order. Another more sophisticated method for control puporses is performed with programmable digital logic. This programmable digital logic is able to execute several actions in parallel with lower execution times than microcontrollers can reach.

The use of microcontrollers due to their flexibility and easy programming features is not always the method of choice. In the case of extensive user interaction or highly complex algorithms the use of microcontrollers can be the preferred solution. But if user interaction is negligible and the control or processing algorithms are of medium or small complexity, low latency is required, programmable digital logic can be the best choise for several reasons:

  • specialized and custom designed digital logic can execute parts of a problem in a parallel kind with lower latency and higher data transfer rates than universel designed microcontrollers, a speed enhancement about 10-20 times can be reached,

  • there is no fixed data path width, that means there are different data path widths which can coexist in the same digital design, and the data width can be adjusted to the actual demands,

  • different local and distributed bus systems can be supported using only one digital component,

  • the power consumption depends strongly on the implemented design, and is not a fixed value like with microcontrollers,

  • the time dynamical behaviour of digital logic is deterministic and can be adjusted with the digital design.

The following figure shows the difference between an implementation of an algorithm with a traditional microcontroller concept and a digital logic approach [1].

Vergleich CPU FPGA


The latency of a microcontroller based system is calculated with t1=12 * clock cycles and depends on the length of the algorithm to be implemented. The latency of a pure digital logic implementing the same algorithm is only t2=2 * digital gate delay << t1. The above shown simple algorithm requires only three digital logic gates, but the microncontroller in contrast is build from about several thousand logic gates.

Reprogrammable digital devices stand for the best compromise between rapid prototyping and the price-power ratio. Small sized digital logic devices are GAL- and PAL-devices. They are only used for small combinational logic implementations like bus address decoders. The next level of complexity and features is reached with CPLDs (Complex Programmable Logik Device). The most powerfull devices are FPGAs (Field Programmable Gate Array). FPGAs are equipped with a high count of registers (latches) which make these devices preferrable for the implementation of state machines. CPLDs are more suited for combinational designs.

But the design implementation of a complex control problem, for example a parameter specified current control of a laser diode, or digital image processing, with pure boolean algebra and basic logic gates is a high barrier and a very time consuming way.

An abatract algorithm- and hardware description programming language is instead needed for the solution of such problems for converting complex algortihms into logic gates without knowledge of the hardware structure used. Programming with a high level language like VHDL is best suited for this purpose. This programming language specifies what the digital logic should perform, not how it's implemented. Synthesis programs (like compilers in traditional languages) derive a hardware dependent logic circuit from the user supplied VHDL source code. The VHDL language is similar to the imperative programming language Modula or Pascal. Parts of the solution of a problem are divided into modules. There are imperative control structures like conditional branching (if then else) or loops (for). But they have a different meaning because all code is executed in parallel! Such parallel task are described with so called processes.

Fields of apllication of FPGAs in the optical design, measuring and laboratory technologies:

  • optical time correlators
  • optical space (image) correlators, for example for distiortion measurements,
  • digital image processing
  • digital space and time resolved filter of arbitrary order,
  • control techniques, for exampel laser diode control,
  • control and analysis of a distance measurement with traveltime measurements,
  • direct coupling of FPGAs to image sensors (zero, one and two dimensional detectors) for data acquisition, storage and analysis.

FPGA Design


Folgende Abbildung zeigt den Entwicklungsablauf:

FPGA design


SPACON1


SPACON1 is a universal FPGA prototype board. This board can be extended with additional IO modules, like AD- and DA convertes.

I.) Schematics

SPACOn Schema


II.) Figure

The following figure shows the inhouse manufactured and assembled FPGA basic board with an Xilinx Spartan-II (TM) FPGA


FPGA Basisplatine

Click for larger image


This baisc board contains the following components:

  1. Power supply for the FPGA (2.5V Core & 3.3V IO), built from switching converts in down conversion mode, assembled on the back side of the PCB,
  2. one XC2S50 Xilinx FPGA,
  3. 30 universal IO lines and 4 clock (input) lines,
  4. one crystal oscillator,
  5. one JTGA port for direct FPGA programming,
  6. and one serial EEPROM for non volatile programming of the FPGA.

SPADC1


SPADC1 is an addon board for the FPGA evaluation board SPACON1. It contains Analog-to-Digital and Digital-to-Analog Converters directly connected to the IO lines of the FPGA. Sampling rates upto 1 M Sample/s are provided.

I.) Schematics

SPADC Schema


II.) Figure

Teh following figure shows the inhous manufactured and assembled AD/DA board. This module is already connected to the above shown SPACON1 FPGA evaluation base board.


FPGA Basisplatine

Click for larger image


This extension board contains the following components:

  1. Power supply for both the analog and digtal parts,
  2. Two AD-Converter with 12 bit resolution. The conversion time is about 0.8 microseconds. The input of teh AD-Convertes are decoupled with rail-to-rail operational amplifiers.
  3. One DA-Converter with two channels and 12 bit resolution. The settling time of the output signal is about 0.5 microseconds. The outputs of the DA-Converters are decoupled with rail-to-rail operational amplifiers.


Example VHDL Code

The following VHDL sourcecode performs these oeprations:

  1. Execute one AD-Conversion,
  2. Read the result of the conversion,
  3. Write the latched result to the DA-Converter..

This algorithm was implemented with a Moore-like state machine.

--      ==================================
--      OOOO   OOOO OOOO  O      O   OOOO
--      O   O  O    O     O     O O  O   O
--      O   O  O    O     O     O O  O   O
--      OOOO   OOOO OOOO  O     OOO  OOOO
--      O   O     O    O  O    O   O O   O
--      O   O     O    O  O    O   O O   O
--      OOOO   OOOO OOOO  OOOO O   O OOOO
--      ==================================
--      BSSLAB, Dr. Stefan Bosse sci@bsslab.de
--
--    PROTECTED BY AND DISTRIBUTED UNDER THE TERMS OF:
--    Free Software Foundation-Europe, GNU GPL License, Version 2
--
--    $AUTHORS:     Stefan Bosse
--    $INITIAL:     (C) 2005 BSSLAB
--    $CREATED:     16.4.2005
--    $VERSION:     1.01
--
--    $INFO:
--
--
-- SPACON1 + SPADC 
-- ADC + DAC test
--
--
--    $ENDOFINFO
--


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;


entity adctest is
    port (
        CLK_EXT: in std_logic;                       -- CLK input from Q_Oscillator
        QA: out std_logic;
        QB: out std_logic;
        DB: inout std_logic_vector (11 downto 0); -- Databus
        DAC_CSA: out std_logic;  -- Chip select DAC A
        DAC_CSB: out std_logic;  -- Chip select DAC B
        DAC_WR: out std_logic;   -- DAC Write
        ADC1_RD: out std_logic;   -- ADC read
        ADC1_CONVST: out std_logic; -- ADC conversion start
        ADC1_BUSY: in std_logic;    -- ADC busy flag
        ADC2_RD: out std_logic;     -- ADC read
        ADC2_CONVST: out std_logic; -- ADC conversion start
        ADC2_BUSY: in std_logic     -- ADC busy flag
        );
end entity adctest;

architecture main of adctest is
    signal adc_data_a: std_logic_vector (11 downto 0) := "100000000000";
    signal adc_data_b: std_logic_vector (11 downto 0) := "100000000000";
    signal clk_cnt: std_logic_vector (3 downto 0);   -- clk divider
    signal clk: std_logic;  -- internal system clock
    signal dummya,dummyb: std_logic;
    type adc_states is (S_start,
                        S_conv_a,
                        S_busy_a,
                        S_rd_a,
                        S_wr1_a,
                        S_wr2_a,
                        S_end);
    signal adc_state,adc_state_next : adc_states;
    signal adc_rd_a: std_logic;
begin

    clk_div: process (CLK_EXT) is
    begin
        if (CLK_EXT'event and CLK_EXT='1') then
            clk_cnt <= clk_cnt + 1;
        end if;        
    end process clk_div;



    -- state shifter
    state_shift: process (clk) is
    begin
        if (clk'event and clk = '1') then
            adc_state <= adc_state_next;
        end if;
    end process state_shift; 

    -- state processing
    state_proc: process (adc_state,
                         adc_data_a,
                         ADC1_BUSY) is
    begin
        case adc_state is
            when S_start => 
                            DB <= (others => 'Z');
                            DAC_CSA <= '1';
                            DAC_CSB <= '1';
                            DAC_WR <= '1';
                            ADC1_RD <= '1';
                            ADC1_CONVST <= '1';                            
                            adc_rd_a <= '0';
                            adc_state_next <= S_conv_a;
        
            when S_conv_a =>
                            DB <= (others => 'Z');
                            DAC_CSA <= '1';
                            DAC_CSB <= '1';
                            DAC_WR <= '1';
                            ADC1_RD <= '1';
                            ADC1_CONVST <= '0';                            
                            adc_rd_a <= '0';
                            adc_state_next <= S_busy_a;
            when S_busy_a =>
                            DB <= (others => 'Z');
                            DAC_CSA <= '1';
                            DAC_CSB <= '1';
                            DAC_WR <= '1';
                            ADC1_RD <= '1';
                            ADC1_CONVST <= '1';                            
                            adc_rd_a <= '0';

                            if (ADC1_BUSY = '0') then
                                adc_state_next <= S_busy_a;
                            else
                                adc_state_next <= S_rd_a;
                            end if;

            when S_rd_a =>
                            DB <= (others => 'Z');
                            DAC_CSA <= '1';
                            DAC_CSB <= '1';
                            DAC_WR <= '1';
                            ADC1_RD <= '0';
                            ADC1_CONVST <= '1';                            
                            adc_rd_a <= '1';
                            adc_state_next <= S_wr1_a;

            when S_wr1_a => 
                            DB <= adc_data_a;
                            DAC_CSA <= '0';
                            DAC_CSB <= '1';
                            DAC_WR <= '0';
                            ADC1_RD <= '1';
                            ADC1_CONVST <= '1';                            
                            adc_rd_a <= '0';
                            adc_state_next <= S_wr2_a;

            when S_wr2_a => 
                            DB <= adc_data_a;
                            DAC_WR <= '1';
                            DAC_CSA <= '1';
                            DAC_CSB <= '1';
                            ADC1_RD <= '1';
                            ADC1_CONVST <= '1';                            
                            adc_rd_a <= '0';
                            adc_state_next <= S_end;


            when S_end =>
                            DB <= (others => 'Z');
                            DAC_CSA <= '1';
                            DAC_CSB <= '1';
                            DAC_WR <= '1';
                            ADC1_RD <= '1';
                            ADC1_CONVST <= '1';                            
                            adc_rd_a <= '0';
                            adc_state_next <= S_start;
        end case;
    end process state_proc;

    read_a : process (clk,adc_rd_a) is
    begin
        if (clk'event and clk = '1') then
            if (adc_rd_a = '1') then
                adc_data_a(10 downto 0) <= DB(10 downto 0);
                adc_data_a(11) <=  not DB(11);
            end if;
        end if;
    end process read_a;

    -- dummy logic
    QA <= clk_cnt(3) and ADC1_BUSY;
    QB <= clk_cnt(2) and ADC2_BUSY;

    clk <= CLK_EXT;


    ADC2_RD <= '1';
    ADC2_CONVST <= '1';


end architecture main; 


PC104-to-SLI-Bus Bridge

The SLI (Simple Local Interface) -Bus servers as a simple and flexible connection of peripherial components to the PC104 embedded systems bus. The SLI-Bus provides the following data lines and control signals:

  • 8 bidirectional data lines D0..D7
  • 4 address lines A0..A3
  • One RD- and WR signal for read and write requests to peripherial devices
  • 2 universal control lines C0 and C1, for example for interrupt support.

The SLI-Bus convert also implements an interval timer which can trigger system interrupts in user configured time intervalls.

Fields of application:

  • Measureing and control devices like AD convertes
  • rapid prototyping
  • digital logic and mayn more.

The following picture shows an prototype implementation of this SLI-Bus converter connected on the top to a PC104 system. The bus converter was realized with a CPLD device.


FPGA Basisplatine

Click for larger image

The Implementation of the Bus-convertes was done with VHDL. The following Projectresources are available:


--      ==================================
--      OOOO   OOOO OOOO  O      O   OOOO
--      O   O  O    O     O     O O  O   O
--      O   O  O    O     O     O O  O   O
--      OOOO   OOOO OOOO  O     OOO  OOOO
--      O   O     O    O  O    O   O O   O
--      O   O     O    O  O    O   O O   O
--      OOOO   OOOO OOOO  OOOO O   O OOOO
--      ==================================
--      BSSLAB, Dr. Stefan Bosse www.bsslab.de
--
--    PROTECTED BY AND DISTRIBUTED UNDER THE TERMS OF:
--    Free Software Foundation-Europe, GNU GPL License, Version 2
--
--    $MODIFIEDBY:  BSSLAB
--    $AUTHORS:     Stefan Bosse
--    $INITIAL:     (C) 2005 BSSLAB
--    $CREATED:
--    $VERSION:     1.01
--
--    $INFO:
--
--
-- SD-PC104 to SLI (simple local interface) bus translator
--
--    $ENDOFINFO

Library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;


entity sli104_en is
port (
    -- PC104 bus signals
    RESET       : in std_logic;
    MEMW        : in std_logic;
    MEMR        : in std_logic;
    IOW         : in std_logic;
    IOR         : in std_logic;
    CLK         : in std_logic;     -- 6..8 MHz
    IRQ5        : out std_logic;
    IRQ3        : out std_logic;
    ALE         : in std_logic;
    AEN         : in std_logic;

    SD          : inout std_logic_vector(7 downto 0);
    SA          : in std_logic_vector(19 downto 0);

    --
    -- SLI bus
    --

    -- JA connector -> SLI data bus
    SLI_DB          : inout std_logic_vector(7 downto 0);

    -- JB connector first 4 bits -> SLI address bus
    SLI_AB          : out std_logic_vector(3 downto 0);

    -- JB connector last 4 bits: RD,WR,NC,NC
    SLI_RD          : out std_logic;
    SLI_WR          : out std_logic

    );
end sli104_en;

architecture main of sli104_en is
    --
    -- PC104 bus side
    --
    signal clk_count        : std_logic_vector (3 downto 0);
    signal sd_data          : std_logic_vector (7 downto 0);
    signal cs_reg_timer     : std_logic := '0';
    signal cs_reg_conf      : std_logic := '0';
    signal cs_reg_id        : std_logic := '0';
    signal cs_sli           : std_logic := '0';
    signal sd_read          : std_logic := '0';
    signal sd_write         : std_logic := '0';
    signal cs_io104         : std_logic := '0';

    --
    -- PC104 id register
    -- MSB(4): Type -> B
    -- LSB(4): Revision
    --
    constant id_reg    : std_logic_vector (7 downto 0) := X"B1";

    --
    -- Configuration register
    --

    --   
    --  Bit 0: Enable Interrupts
    --  Bit 1: Select IRQ3/IRQ5
    --  Bit 2: Enable Interval Timer with Interrupt
    --

    signal conf_reg    : std_logic_vector (7 downto 0) := "00000000";

    signal enable_irq   : std_logic;
    signal irq_num      : std_logic;
    signal enable_timer : std_logic;

    --
    -- Timer register
    --
    signal timer_reg    : std_logic_vector (7 downto 0) := 
                                (others => '0');



    -- IO address space
    constant io_addr_base       : std_logic_vector (15 downto 0) 
                                    := X"0800";
    constant io_addr_id_reg     : std_logic_vector (15 downto 0)
                                    := io_addr_base + 16;
    constant io_addr_conf_reg   : std_logic_vector (15 downto 0)
                                    := io_addr_base + 17;
    constant io_addr_timer_reg  : std_logic_vector (15 downto 0)
                                    := io_addr_base + 18;

    
    --
    -- Up to 16 SLI devices can be addressed 
    --
    constant io_addr_sli_mask   : std_logic_vector (15 downto 4)
                                    := io_addr_base (15 downto 4);

    

    --
    -- SLI bus side
    --
    signal sli_read     : std_logic := '0';
    signal sli_write    : std_logic := '0';

    --
    -- 1 Byte FIFO - one for each direction
    --   out: from SLI to SD (read operation)
    --    in: from SD to SLI  (write operation)
    --

    signal sli_data_in   : std_logic_vector (7 downto 0);
    signal sli_data_out  : std_logic_vector (7 downto 0);
    

    --
    -- State machine
    --
    type io104_states is (
                          S_wait,
                          S_read_sd,
                          S_read_sli,
                          S_read_finished,
                          S_write_sd,
                          S_write_sli,
                          S_write_finished
            );

    signal io104_state: io104_states := S_wait; 
    signal io104_next_state: io104_states := S_wait;


    --
    -- Buildin interval timer
    --
    type timer_states is (
                          S_timer_start,
                          S_timer_count,
                          S_timer_irq);

    signal timer_state: timer_states := S_timer_start; 
    signal timer_next_state: timer_states := S_timer_start;
    signal timer_count : std_logic := '0';

    --
    -- the counter - only the upper 8 bits are compared with
    -- the timer_reg content
    --
    signal timer_counter : std_logic_vector (15 downto 0) :=
                                (others => '0');
    --
    -- timer clock derived from PC104 bu clock (6..8 MHz div n)
    --
    signal timer_clk    : std_logic;

begin
    --
    -- clock divider
    --

    clk_div: process (CLK,RESET)
    begin
        if (RESET='1') then
            clk_count <= (others => '0');
        elsif (CLK'event and 
               CLK = '1') then
            clk_count <= clk_count + 1;
        end if;
    end process;

    --
    -- CLK=8MHz => 125ns period div 16 => 2us period time
    --
    timer_clk <= clk_count(3);


    --
    -- state shifter
    --

    state_shifter: process (CLK,RESET)
    begin
        if (RESET = '1') then
            io104_state <= S_wait;
        elsif (CLK'event and CLK = '1') then
            io104_state <= io104_next_state;
        end if;
    end process;


    --
    -- state processing
    -- 

    state_proc: process (io104_state,
                         IOR,
                         IOW, 
                         cs_io104,
                         cs_sli)
    begin   
        case io104_state is

            when S_wait =>
                if (IOR = '0' and cs_io104 = '1') then
                        sd_read  <= '0';
                        sd_write <= '0';
                        sli_read  <= '0';
                        sli_write <= '0';
                        io104_next_state <= S_read_sd;
                elsif (IOW = '0' and cs_io104 = '1') then
                        sd_read  <= '0';
                        sd_write <= '0';
                        sli_read  <= '0';
                        sli_write <= '0';
                        io104_next_state <= S_write_sd;
                else
                        sd_read  <= '0';
                        sd_write <= '0';
                        sli_read  <= '0';
                        sli_write <= '0';
                        io104_next_state <= S_wait;
                end if;

            when S_read_sd =>
                sd_write <= '0';
                sd_read  <= '1';
                if (cs_sli = '1') then 
                    sli_read  <= '1';
                else
                    sli_read  <= '0';
                end if;
                sli_write <= '0';

                io104_next_state <= S_read_sli;

            when S_read_sli =>
                sd_write <= '0';
                sd_read  <= '1';
                sli_read  <= '0';
                sli_write <= '0';

                if (IOR ='1' or cs_io104 = '0') then
                    io104_next_state <= S_read_finished;
                else 
                    io104_next_state <= S_read_sli;
                end if;

            when S_read_finished =>
                sd_read  <= '0';
                sd_write <= '0';
                sli_read  <= '0';
                sli_write <= '0';
                io104_next_state <= S_wait;

            when S_write_sd =>
                sd_read  <= '0';
                sd_write <= '1';
                sli_read  <= '0';
                sli_write <= '0';

                if (IOW ='1' or cs_io104 = '0') then
                    io104_next_state <= S_write_sli;
                else 
                    io104_next_state <= S_write_sd;
                end if;

            when S_write_sli =>
                sd_read  <= '0';
                sd_write <= '0';
                sli_read  <= '0';
                if (cs_sli = '1') then
                    sli_write <= '1';
                else
                    sli_write <= '0';
                end if;

                io104_next_state <= S_write_finished;

            when S_write_finished =>
                sd_read  <= '0';
                sd_write <= '0';
                sli_read  <= '0';
                sli_write <= '0';
                io104_next_state <= S_wait;
                                                
        end case;                
    end process;



    --
    -- bus read request - multiplex data on the bus
    --
    sd_bus_read: process ( 
                        cs_reg_timer,
                        cs_reg_conf,
                        cs_reg_id,
                        cs_sli,
                        sli_data_out,
                        conf_reg,
                        timer_reg,
                        sd_read)
    begin
        if (sd_read = '1') then
            case std_logic_vector'(
                    cs_sli,
                    cs_reg_timer,
                    cs_reg_conf,  
                    cs_reg_id) is

                when ("1000") =>
                    sd_data <= sli_data_out;
                when ("0100") =>
                    sd_data <= timer_reg;
                when ("0010") =>
                    sd_data <= conf_reg;
                when ("0001") =>
                    sd_data <= id_reg;
                when others =>
                    sd_data <= (others => '0');
            end case;
        else
            sd_data <= (others => '0');
        end if;
    end process;
    --
    -- bus write request - multiplex data from the bus
    --
    sd_bus_write: process (
                        cs_reg_conf,  
                        cs_reg_id,
                        cs_sli,
                        cs_reg_timer,
                        sd_write,
                        SD,
                        CLK)
    begin
        if (CLK'event and CLK = '1') then
            if (sd_write = '1') then
            case std_logic_vector'(
                        cs_reg_timer,
                        cs_reg_conf,  
                        cs_reg_id,
                        cs_sli) is

                when ("0001") =>
                    sli_data_in <= SD;
                when ("0100") =>
                    conf_reg <= SD;
                when ("1000") =>
                    timer_reg <= SD;
                when others =>
                        null;
                end case;
            end if;
        end if;
    end process;





    --
    -- register select
    --
    cs_reg_timer <= '1' when (SA(15 downto 0) = io_addr_timer_reg) and
                        (RESET = '0')
                else '0';
    cs_reg_conf <= '1' when (SA(15 downto 0) = io_addr_conf_reg) and
                        (RESET = '0')
                else '0';
    cs_reg_id <= '1' when (SA(15 downto 0) = io_addr_id_reg) and
                        (RESET = '0')
                else '0';
    cs_sli <= '1' when (SA(15 downto 4) = io_addr_sli_mask) and
                        (RESET = '0')
                else '0';


    --
    -- bus tristate control
    --
    SD <= sd_data when sd_read = '1' 
          else (others => 'Z');

    --
    -- internal control signals
    --
    cs_io104 <= '1' when (cs_reg_timer = '1' or
                          cs_reg_conf = '1' or
                          cs_reg_id = '1'   or
                          cs_sli = '1') and 
                         (RESET = '0')
                 else '0';


    --
    -- Configuration management
    --

    enable_irq      <= conf_reg(0);
    irq_num         <= conf_reg(1);
    enable_timer    <= conf_reg(2);

    --
    -- Timer
    --

    --
    -- timer state shifter
    --

    timer_state_shifter: process (timer_clk,RESET,timer_next_state)
    begin
        if (RESET = '1') then
            timer_state <= S_timer_start;
        elsif (timer_clk'event and timer_clk = '1') then
            timer_state <= timer_next_state;
        end if;
    end process;


    --
    -- timer state processing
    -- 

    timer_state_proc: process (timer_state,
                               enable_timer,
                               enable_irq,
                               timer_reg,
                               timer_counter)

    begin   
        case timer_state is

            when S_timer_start =>
                timer_count <= '0';
                if (enable_timer = '1') then
                    timer_next_state <= S_timer_count;
                else
                    timer_next_state <= S_timer_start; 
                end if;

            when S_timer_count =>
                timer_count <= '1';
                if (timer_counter(15 downto 8) = timer_reg) then
                    timer_next_state <= S_timer_irq;
                else
                    timer_next_state <= S_timer_count;
                end if;
            when S_timer_irq =>
                timer_count <= '0';
                timer_next_state <= S_timer_start;

        end case;
    end process;

    timer: process(timer_clk,timer_count)
    begin
        if timer_count = '0' then
            timer_counter <= (others => '0');
        elsif timer_clk'event and timer_clk = '1' then
            timer_counter <= timer_counter + 1;
        end if;
    end process;

    IRQ3 <= '1' when (enable_irq = '1' and
                      irq_num = '0' and 
                      enable_timer = '1' and
                      timer_state = S_timer_irq) else '0'; 

    IRQ5 <= '1' when (enable_irq = '1' and
                      irq_num = '1' and 
                      enable_timer = '1' and
                      timer_state = S_timer_irq) else '0'; 

    -- 
    -- SLI bus interface side
    --
    SLI_AB <= SA(3 downto 0) when cs_sli = '1' else (others => '0');
    SLI_RD <= sli_read;
    SLI_WR <= sli_write;


    --
    -- SLI bus read request - multiplex data from the bus
    --
    sli_bus_read: process (sli_read,
                           SLI_DB,
                           CLK)
    begin
        if (CLK'event and CLK = '1') then
            if (sli_read = '1') then
                    sli_data_out <= SLI_DB;
            end if;
        end if;
    end process;


    --
    -- bus tristate control
    --
    SLI_DB <= sli_data_in when sli_write = '1' 
                                else (others => 'Z');

end main;

Literature


[1]
M. Wannenmacher
Das FPGA-Kochbuch
IWT-verlag, 1998
[2]
P. Ashenden
The Designer's Guide to VHDL
Morgen-Kaufmann Verlag, 2002

Powered by VAM, Revision 1138111946