----------------------------------------------------------------------------------
-- Company:        ETH Zurich, Institute for Particle Physics
-- Engineer:       Q. Weitzel, P. Vogler
-- 
-- Create Date:    09/13/2010
-- Design Name: 
-- Module Name:    FTU_rs485_control - Behavioral
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description:    top level entity of FTU RS485 module
--
-- Dependencies:
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

library ftu_definitions;
USE ftu_definitions.ftu_array_types.all;
USE ftu_definitions.ftu_constants.all;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity FTU_rs485_control is
  port(
    main_clk                : IN  std_logic;
    brd_add                 : IN  std_logic_vector(5 downto 0);
    rx_d                    : IN  std_logic;
    rates_ready             : IN  std_logic;  -- rate_array_rs485 has now valid rates for sending
    DACs_ready              : IN  std_logic;  -- dac_array_rs485_in is ok for sending
    enables_ready           : IN  std_logic;  -- enable_array_rs485_in is ok for sending
    prescaling_ready        : IN  std_logic;  -- prescaling byte is ok for sending
    ping_pong_ready         : IN  std_logic;  -- ping pong successful
    rate_array_rs485        : IN  rate_array_type;
    overflow_array_rs485_in : IN  STD_LOGIC_VECTOR(7 downto 0);
    dac_array_rs485_in      : IN  dac_array_type;
    enable_array_rs485_in   : IN  enable_array_type;
    prescaling_rs485_in     : IN  STD_LOGIC_VECTOR(7 downto 0);
    dna                     : IN  STD_LOGIC_VECTOR(63 downto 0);
    rx_en                   : OUT std_logic;
    tx_d                    : OUT std_logic;
    tx_en                   : OUT std_logic;
    new_DACs                : OUT std_logic := '0';  -- new DACs arrived via RS485
    new_enables             : OUT std_logic := '0';  -- new enables arrived via RS485
    new_prescaling          : OUT std_logic := '0';  -- new prescaling arrived via RS485
    read_rates              : OUT std_logic := '0';  -- FTM wants to read rates
    read_DACs               : OUT std_logic := '0';  -- FTM wants to read DACs
    read_enables            : OUT std_logic := '0';  -- FTM wants to read enable pattern
    read_prescaling         : OUT std_logic := '0';  -- FTM wants to read prescaling value
    ping_pong               : OUT std_logic := '0';  -- ping pong command from FTM
    dac_array_rs485_out     : OUT dac_array_type;
    enable_array_rs485_out  : OUT enable_array_type;
    prescaling_rs485_out    : OUT STD_LOGIC_VECTOR(7 downto 0)
  );
end FTU_rs485_control;

architecture Behavioral of FTU_rs485_control is

  signal tx_start_sig : std_logic := '0';
  signal tx_data_sig  : std_logic_vector (7 DOWNTO 0) := (others => '0');
  signal tx_busy_sig  : std_logic;  -- initialized in FTU_rs485_interface

  signal rx_valid_sig : std_logic;  -- initialized in FTU_rs485_interface
  signal rx_data_sig  : std_logic_vector (7 DOWNTO 0);  -- initialized in FTU_rs485_interface
  --signal rx_busy_sig  : std_logic;  -- initialized in FTU_rs485_interface

  signal block_valid_sig : std_logic;  -- initialized in FTU_rs485_receiver
  signal data_block_sig  : std_logic_vector(RS485_BLOCK_WIDTH - 1 downto 0);  -- initialized in FTU_rs485_receiver

  signal int_new_DACs_sig        : std_logic;  -- initialized in FTU_rs485_interpreter
  signal int_new_enables_sig     : std_logic;  -- initialized in FTU_rs485_interpreter
  signal int_new_prescaling_sig  : std_logic;  -- initialized in FTU_rs485_interpreter
  signal int_read_rates_sig      : std_logic;  -- initialized in FTU_rs485_interpreter
  signal int_read_DACs_sig       : std_logic;  -- initialized in FTU_rs485_interpreter
  signal int_read_enables_sig    : std_logic;  -- initialized in FTU_rs485_interpreter
  signal int_read_prescaling_sig : std_logic;  -- initialized in FTU_rs485_interpreter
  signal int_ping_pong_sig       : std_logic;  -- initialized in FTU_rs485_interpreter

  signal txcnt : integer range 0 to (RS485_BLOCK_WIDTH / 8) := 0;  -- count 28 1-byte frames 
  
  component FTU_rs485_receiver
    port(
      rec_clk   : in  std_logic;
      --rx_busy   : in  std_logic;
      rec_din   : in  std_logic_vector(7 downto 0);
      rec_den   : in  std_logic;
      rec_dout  : out std_logic_vector(RS485_BLOCK_WIDTH - 1 downto 0);
      rec_valid : out std_logic
    );
  end component;

  component FTU_rs485_interpreter
    port(
      clk                    : IN  std_logic;
      data_block             : IN  std_logic_vector(RS485_BLOCK_WIDTH - 1 downto 0);
      block_valid            : IN  std_logic;
      brd_add                : IN  std_logic_vector(5 downto 0);
      int_new_DACs           : OUT std_logic;
      int_new_enables        : OUT std_logic;
      int_new_prescaling     : OUT std_logic;
      int_read_rates         : OUT std_logic;
      int_read_DACs          : OUT std_logic;
      int_read_enables       : OUT std_logic;
      int_read_prescaling    : OUT std_logic;
      int_ping_pong          : OUT std_logic;
      dac_array_rs485_out    : OUT dac_array_type;
      enable_array_rs485_out : OUT enable_array_type;
      prescaling_rs485_out   : OUT STD_LOGIC_VECTOR(7 downto 0)
    );
  end component;

  component FTU_rs485_interface
    port(
      clk      : IN  std_logic;
      -- RS485
      rx_d     : IN  std_logic;
      rx_en    : OUT std_logic;
      tx_d     : OUT std_logic;
      tx_en    : OUT std_logic;
      -- FPGA
      rx_data  : OUT std_logic_vector (7 DOWNTO 0);
      --rx_busy  : OUT std_logic  := '0';
      rx_valid : OUT std_logic  := '0';
      tx_data  : IN  std_logic_vector (7 DOWNTO 0);
      tx_busy  : OUT std_logic  := '0';
      tx_start : IN  std_logic
    );
  end component;

  type FTU_rs485_control_StateType is (RECEIVE,
                                       READ_RATES_WAIT, READ_DAC_WAIT, READ_ENABLE_WAIT, READ_PRESCALING_WAIT,
                                       SET_DAC_WAIT, SET_ENABLE_WAIT, SET_PRESCALING_WAIT, PING_PONG_WAIT,
                                       READ_RATES_TRANSMIT, READ_DAC_TRANSMIT, READ_ENABLE_TRANSMIT, READ_PRESCALING_TRANSMIT,
                                       SET_DAC_TRANSMIT, SET_ENABLE_TRANSMIT, SET_PRESCALING_TRANSMIT, PING_PONG_TRANSMIT);
  signal FTU_rs485_control_State : FTU_rs485_control_StateType;
  
begin
  
  Inst_FTU_rs485_receiver : FTU_rs485_receiver
    port map(
      rec_clk   => main_clk,
      --rx_busy   =>,
      rec_din   => rx_data_sig,
      rec_den   => rx_valid_sig,
      rec_dout  => data_block_sig,
      rec_valid => block_valid_sig
    );

  Inst_FTU_rs485_interpreter : FTU_rs485_interpreter
    port map(
      clk                    => main_clk,
      data_block             => data_block_sig,
      block_valid            => block_valid_sig,
      brd_add                => brd_add,
      int_new_DACs           => int_new_DACs_sig,
      int_new_enables        => int_new_enables_sig,
      int_new_prescaling     => int_new_prescaling_sig,
      int_read_rates         => int_read_rates_sig,
      int_read_DACs          => int_read_DACs_sig,
      int_read_enables       => int_read_enables_sig,
      int_read_prescaling    => int_read_prescaling_sig,
      int_ping_pong          => int_ping_pong_sig,
      dac_array_rs485_out    => dac_array_rs485_out,
      enable_array_rs485_out => enable_array_rs485_out,
      prescaling_rs485_out   => prescaling_rs485_out
    );

  Inst_FTU_rs485_interface : FTU_rs485_interface
    port map(
      clk      => main_clk,
      -- RS485
      rx_d     => rx_d,
      rx_en    => rx_en,
      tx_d     => tx_d,
      tx_en    => tx_en,
      -- FPGA
      rx_data  => rx_data_sig,
      --rx_busy  => rx_busy_sig,
      rx_valid => rx_valid_sig,
      tx_data  => tx_data_sig,
      tx_busy  => tx_busy_sig,
      tx_start => tx_start_sig
    );

  --FTU RS485 control finite state machine

  FTU_rs485_control_FSM: process (main_clk)
  begin
    if Rising_edge(main_clk) then
      case FTU_rs485_control_State is
        
        when RECEIVE =>  -- default state, receiver on, no transmission          
          tx_start_sig <= '0';
          if (int_new_DACs_sig = '1') then
            new_DACs        <= '1';
            new_enables     <= '0';
            new_prescaling  <= '0';
            read_rates      <= '0';
            read_DACs       <= '0';
            read_enables    <= '0';
            read_prescaling <= '0';
            ping_pong       <= '0';
            FTU_rs485_control_State <= SET_DAC_WAIT;
          elsif (int_new_DACs_sig = '0' and int_new_enables_sig = '1') then
            new_DACs        <= '0';
            new_enables     <= '1';
            new_prescaling  <= '0';
            read_rates      <= '0';
            read_DACs       <= '0';
            read_enables    <= '0';
            read_prescaling <= '0';
            ping_pong       <= '0';
            FTU_rs485_control_State <= SET_ENABLE_WAIT;
          elsif (int_new_DACs_sig = '0' and int_new_enables_sig = '0' and int_new_prescaling_sig = '1') then
            new_DACs        <= '0';
            new_enables     <= '0';
            new_prescaling  <= '1';
            read_rates      <= '0';
            read_DACs       <= '0';
            read_enables    <= '0';
            read_prescaling <= '0';
            ping_pong       <= '0';
            FTU_rs485_control_State <= SET_PRESCALING_WAIT;
          elsif (int_new_DACs_sig = '0' and int_new_enables_sig = '0' and int_new_prescaling_sig = '0' and
                 int_read_rates_sig = '1') then
            new_DACs        <= '0';
            new_enables     <= '0';
            new_prescaling  <= '0';
            read_rates      <= '1';
            read_DACs       <= '0';
            read_enables    <= '0';
            read_prescaling <= '0';
            ping_pong       <= '0';
            FTU_rs485_control_State <= READ_RATES_WAIT;
          elsif (int_new_DACs_sig = '0' and int_new_enables_sig = '0' and int_new_prescaling_sig = '0' and
                 int_read_rates_sig = '0' and int_read_DACs_sig = '1') then
            new_DACs        <= '0';
            new_enables     <= '0';
            new_prescaling  <= '0';
            read_rates      <= '0';
            read_DACs       <= '1';
            read_enables    <= '0';
            read_prescaling <= '0';
            ping_pong       <= '0';
            FTU_rs485_control_State <= READ_DAC_WAIT;
          elsif (int_new_DACs_sig = '0' and int_new_enables_sig = '0' and int_new_prescaling_sig = '0' and
                 int_read_rates_sig = '0' and int_read_DACs_sig = '0' and int_read_enables_sig = '1') then
            new_DACs        <= '0';
            new_enables     <= '0';
            new_prescaling  <= '0';
            read_rates      <= '0';
            read_DACs       <= '0';
            read_enables    <= '1';
            read_prescaling <= '0';
            ping_pong       <= '0';
            FTU_rs485_control_State <= READ_ENABLE_WAIT;
          elsif (int_new_DACs_sig = '0' and int_new_enables_sig = '0' and int_new_prescaling_sig = '0' and
                 int_read_rates_sig = '0' and int_read_DACs_sig = '0' and int_read_enables_sig = '0' and int_read_prescaling_sig = '1') then
            new_DACs        <= '0';
            new_enables     <= '0';
            new_prescaling  <= '0';
            read_rates      <= '0';
            read_DACs       <= '0';
            read_enables    <= '0';
            read_prescaling <= '1';
            ping_pong       <= '0';
            FTU_rs485_control_State <= READ_PRESCALING_WAIT;
          elsif (int_new_DACs_sig = '0' and int_new_enables_sig = '0' and int_new_prescaling_sig = '0' and
                 int_read_rates_sig = '0' and int_read_DACs_sig = '0' and int_read_enables_sig = '0' and int_read_prescaling_sig = '0' and
                 int_ping_pong_sig = '1') then
            new_DACs        <= '0';
            new_enables     <= '0';
            new_prescaling  <= '0';
            read_rates      <= '0';
            read_DACs       <= '0';
            read_enables    <= '0';
            read_prescaling <= '0';
            ping_pong       <= '1';
            FTU_rs485_control_State <= PING_PONG_WAIT;
          else
            new_DACs        <= '0';
            new_enables     <= '0';
            new_prescaling  <= '0';
            read_rates      <= '0';
            read_DACs       <= '0';
            read_enables    <= '0';
            read_prescaling <= '0';
            ping_pong       <= '0';
            FTU_rs485_control_State <= RECEIVE;
          end if;

        when SET_DAC_WAIT=>  -- wait until FTU control says "done" and then answer to FTM
          if (DACs_ready = '1') then
            new_DACs <= '0';
            FTU_rs485_control_State <= SET_DAC_TRANSMIT;
          else
            new_DACs <= '1';
            FTU_rs485_control_State <= SET_DAC_WAIT;
          end if;

        when SET_ENABLE_WAIT =>  -- wait until FTU control says "done" and then answer to FTM
          if (enables_ready = '1') then
            new_enables <= '0';
            FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;
          else
            new_enables <= '1';
            FTU_rs485_control_State <= SET_ENABLE_WAIT;
          end if;

        when SET_PRESCALING_WAIT =>  -- wait until FTU control says "done" and then answer to FTM
          if (prescaling_ready = '1') then
            new_prescaling <= '0';
            FTU_rs485_control_State <= SET_PRESCALING_TRANSMIT;
          else
            new_prescaling <= '1';
            FTU_rs485_control_State <= SET_PRESCALING_WAIT;
          end if;

        when READ_RATES_WAIT =>  -- wait until FTU control says "done" and then answer to FTM
          if (rates_ready = '1') then
            read_rates <= '0';
            FTU_rs485_control_State <= READ_RATES_TRANSMIT;
          else
            read_rates <= '1';
            FTU_rs485_control_State <= READ_RATES_WAIT;
          end if;

        when READ_DAC_WAIT =>  -- wait until FTU control says "done" and then answer to FTM
          if (DACs_ready = '1') then
            read_DACs <= '0';
            FTU_rs485_control_State <= READ_DAC_TRANSMIT;
          else
            read_DACs <= '1';
            FTU_rs485_control_State <= READ_DAC_WAIT;
          end if;

        when READ_ENABLE_WAIT =>  -- wait until FTU control says "done" and then answer to FTM
          if (enables_ready = '1') then
            read_enables <= '0';
            FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;
          else
            read_enables <= '1';
            FTU_rs485_control_State <= READ_ENABLE_WAIT;
          end if;

        when READ_PRESCALING_WAIT =>  -- wait until FTU control says "done" and then answer to FTM
          if (prescaling_ready = '1') then
            read_prescaling <= '0';
            FTU_rs485_control_State <= READ_PRESCALING_TRANSMIT;
          else
            read_prescaling <= '1';
            FTU_rs485_control_State <= READ_PRESCALING_WAIT;
          end if;

        when PING_PONG_WAIT =>  -- wait until FTU control says "done" and then answer to FTM
          if (ping_pong_ready = '1') then
            ping_pong <= '0';
            FTU_rs485_control_State <= PING_PONG_TRANSMIT;
          else
            ping_pong <= '1';
            FTU_rs485_control_State <= PING_PONG_WAIT;
          end if;
          
        when SET_DAC_TRANSMIT =>
          if tx_busy_sig = '0' then
            if txcnt = 0 then           -- start delimiter
              txcnt <= txcnt + 1;
              tx_data_sig <= RS485_START_DELIM;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_DAC_TRANSMIT;
            elsif txcnt = 1 then        -- FTM address
              txcnt <= txcnt + 1;
              tx_data_sig <= FTM_ADDRESS;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_DAC_TRANSMIT;
            elsif txcnt = 2 then        -- board address
              txcnt <= txcnt + 1;
              tx_data_sig <= "00" & brd_add;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_DAC_TRANSMIT;
            elsif txcnt = 3 then        -- firmware ID
              txcnt <= txcnt + 1;
              tx_data_sig <= FIRMWARE_ID;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_DAC_TRANSMIT;
            elsif txcnt = 4 then        -- mirrored command
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_DAC_TRANSMIT;
            elsif txcnt = 5 then        -- data: DAC A low
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(0),16)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_DAC_TRANSMIT;
            elsif txcnt = 6 then        -- data: DAC A high
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(0),16)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_DAC_TRANSMIT;
            elsif txcnt = 7 then        -- data: DAC B low
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(1),16)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_DAC_TRANSMIT;
            elsif txcnt = 8 then        -- data: DAC B high
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(1),16)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_DAC_TRANSMIT;
            elsif txcnt = 9 then        -- data: DAC C low
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(2),16)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_DAC_TRANSMIT;
            elsif txcnt = 10 then        -- data: DAC C high
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(2),16)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_DAC_TRANSMIT;
            elsif txcnt = 11 then        -- data: DAC D low
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(3),16)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_DAC_TRANSMIT;
            elsif txcnt = 12 then        -- data: DAC D high
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(3),16)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_DAC_TRANSMIT;
            elsif txcnt = 13 then        -- data: DAC E low
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(7),16)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_DAC_TRANSMIT;
            elsif txcnt = 14 then        -- data: DAC E high
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(7),16)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_DAC_TRANSMIT;
            elsif txcnt < ((RS485_BLOCK_WIDTH / 8) - 2) then        -- data: not used
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_DAC_TRANSMIT;
            elsif txcnt = ((RS485_BLOCK_WIDTH / 8) - 2) then        -- CRC error counter
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";  -- NOT YET IMPLEMENTED!!!
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = ((RS485_BLOCK_WIDTH / 8) - 1) then        -- check sum
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";  -- NOT YET IMPLEMENTED!!!
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_DAC_TRANSMIT;              
            else                        -- transmission finished
              txcnt <= 0;
              FTU_rs485_control_State <= RECEIVE;
            end if;
          else
            tx_start_sig <= '0';
            FTU_rs485_control_State <= SET_DAC_TRANSMIT;
          end if;

        when SET_ENABLE_TRANSMIT =>
          if tx_busy_sig = '0' then
            if txcnt = 0 then           -- start delimiter
              txcnt <= txcnt + 1;
              tx_data_sig <= RS485_START_DELIM;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;
            elsif txcnt = 1 then        -- FTM address
              txcnt <= txcnt + 1;
              tx_data_sig <= FTM_ADDRESS;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;
            elsif txcnt = 2 then        -- board address
              txcnt <= txcnt + 1;
              tx_data_sig <= "00" & brd_add;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;
            elsif txcnt = 3 then        -- firmware ID
              txcnt <= txcnt + 1;
              tx_data_sig <= FIRMWARE_ID;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;
            elsif txcnt = 4 then        -- mirrored command
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000011";
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;
            elsif txcnt = 5 then        -- data: enable pattern A7-0
              txcnt <= txcnt + 1;
              tx_data_sig <= enable_array_rs485_in(0)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;
            elsif txcnt = 6 then        -- data: enable pattern A8
              txcnt <= txcnt + 1;
              tx_data_sig <= enable_array_rs485_in(0)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;
            elsif txcnt = 7 then        -- data: enable pattern B7-0
              txcnt <= txcnt + 1;
              tx_data_sig <= enable_array_rs485_in(1)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;
            elsif txcnt = 8 then        -- data: enable pattern B8
              txcnt <= txcnt + 1;
              tx_data_sig <= enable_array_rs485_in(1)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;
            elsif txcnt = 9 then        -- data: enable pattern C7-0
              txcnt <= txcnt + 1;
              tx_data_sig <= enable_array_rs485_in(2)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;
            elsif txcnt = 10 then        -- data: enable pattern C8
              txcnt <= txcnt + 1;
              tx_data_sig <= enable_array_rs485_in(2)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;
            elsif txcnt = 11 then        -- data: enable pattern D7-0
              txcnt <= txcnt + 1;
              tx_data_sig <= enable_array_rs485_in(3)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;
            elsif txcnt = 12 then        -- data: enable pattern D8
              txcnt <= txcnt + 1;
              tx_data_sig <= enable_array_rs485_in(3)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;
            elsif txcnt < ((RS485_BLOCK_WIDTH / 8) - 2) then        -- data: not used
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;
            elsif txcnt = ((RS485_BLOCK_WIDTH / 8) - 2) then        -- CRC error counter
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";  -- NOT YET IMPLEMENTED!!!
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;
            elsif txcnt = ((RS485_BLOCK_WIDTH / 8) - 1) then        -- check sum
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";  -- NOT YET IMPLEMENTED!!!
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;        
            else                        -- transmission finished
              txcnt <= 0;
              FTU_rs485_control_State <= RECEIVE;
            end if;
          else
            tx_start_sig <= '0';
            FTU_rs485_control_State <= SET_ENABLE_TRANSMIT;
          end if;

        when SET_PRESCALING_TRANSMIT =>
          if tx_busy_sig = '0' then
            if txcnt = 0 then           -- start delimiter
              txcnt <= txcnt + 1;
              tx_data_sig <= RS485_START_DELIM;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_PRESCALING_TRANSMIT;
            elsif txcnt = 1 then        -- FTM address
              txcnt <= txcnt + 1;
              tx_data_sig <= FTM_ADDRESS;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_PRESCALING_TRANSMIT;
            elsif txcnt = 2 then        -- board address
              txcnt <= txcnt + 1;
              tx_data_sig <= "00" & brd_add;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_PRESCALING_TRANSMIT;
            elsif txcnt = 3 then        -- firmware ID
              txcnt <= txcnt + 1;
              tx_data_sig <= FIRMWARE_ID;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_PRESCALING_TRANSMIT;
            elsif txcnt = 4 then        -- mirrored command
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000110";
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_PRESCALING_TRANSMIT;
            elsif txcnt = 5 then        -- data: prescaling
              txcnt <= txcnt + 1;
              tx_data_sig <= prescaling_rs485_in;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_PRESCALING_TRANSMIT;
            elsif txcnt < ((RS485_BLOCK_WIDTH / 8) - 2) then        -- data: not used
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_PRESCALING_TRANSMIT;
            elsif txcnt = ((RS485_BLOCK_WIDTH / 8) - 2) then        -- CRC error counter
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";  -- NOT YET IMPLEMENTED!!!
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_PRESCALING_TRANSMIT;
            elsif txcnt = ((RS485_BLOCK_WIDTH / 8) - 1) then        -- check sum
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";  -- NOT YET IMPLEMENTED!!!
              tx_start_sig <= '1';
              FTU_rs485_control_State <= SET_PRESCALING_TRANSMIT;
            else                        -- transmission finished
              txcnt <= 0;
              FTU_rs485_control_State <= RECEIVE;
            end if; 
          else
            tx_start_sig <= '0';
            FTU_rs485_control_State <= SET_PRESCALING_TRANSMIT;
          end if;

        when READ_RATES_TRANSMIT =>
          if tx_busy_sig = '0' then
            if txcnt = 0 then           -- start delimiter
              txcnt <= txcnt + 1;
              tx_data_sig <= RS485_START_DELIM;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 1 then        -- FTM address
              txcnt <= txcnt + 1;
              tx_data_sig <= FTM_ADDRESS;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 2 then        -- board address
              txcnt <= txcnt + 1;
              tx_data_sig <= "00" & brd_add;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 3 then        -- firmware ID
              txcnt <= txcnt + 1;
              tx_data_sig <= FIRMWARE_ID;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 4 then        -- mirrored command
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000010";
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 5 then        -- data: counter A 7...0
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(0),32)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 6 then        -- data: counter A 15...8
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(0),32)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 7 then        -- data: counter A 23...16
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(0),32)(23 downto 16);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 8 then        -- data: counter A 31...24
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(0),32)(31 downto 24);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 9 then        -- data: counter B 7...0
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(1),32)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 10 then        -- data: counter B 15...8
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(1),32)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 11 then        -- data: counter B 23...16
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(1),32)(23 downto 16);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 12 then        -- data: counter B 31...24
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(1),32)(31 downto 24);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 13 then        -- data: counter C 7...0
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(2),32)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 14 then        -- data: counter C 15...8
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(2),32)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 15 then        -- data: counter C 23...16
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(2),32)(23 downto 16);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 16 then        -- data: counter C 31...24
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(2),32)(31 downto 24);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 17 then        -- data: counter D 7...0
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(3),32)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 18 then        -- data: counter D 15...8
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(3),32)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 19 then        -- data: counter D 23...16
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(3),32)(23 downto 16);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 20 then        -- data: counter D 31...24
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(3),32)(31 downto 24);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 21 then        -- data: trigger counter 7...0
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(4),32)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 22 then        -- data: trigger counter 15...8
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(4),32)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 23 then        -- data: trigger counter 23...16
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(4),32)(23 downto 16);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 24 then        -- data: trigger counter 31...24
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(rate_array_rs485(4),32)(31 downto 24);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = 25 then        -- data: overflow register
              txcnt <= txcnt + 1;
              tx_data_sig <= overflow_array_rs485_in;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = ((RS485_BLOCK_WIDTH / 8) - 2) then        -- CRC error counter
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";  -- NOT YET IMPLEMENTED!!!
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            elsif txcnt = ((RS485_BLOCK_WIDTH / 8) - 1) then        -- check sum
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";  -- NOT YET IMPLEMENTED!!!
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_RATES_TRANSMIT;
            else                        -- transmission finished
              txcnt <= 0;
              FTU_rs485_control_State <= RECEIVE;
            end if;  
          else
            tx_start_sig <= '0';
            FTU_rs485_control_State <= READ_RATES_TRANSMIT;
          end if;

        when READ_DAC_TRANSMIT =>
          if tx_busy_sig = '0' then
            if txcnt = 0 then           -- start delimiter
              txcnt <= txcnt + 1;
              tx_data_sig <= RS485_START_DELIM;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;
            elsif txcnt = 1 then        -- FTM address
              txcnt <= txcnt + 1;
              tx_data_sig <= FTM_ADDRESS;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;
            elsif txcnt = 2 then        -- board address
              txcnt <= txcnt + 1;
              tx_data_sig <= "00" & brd_add;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;
            elsif txcnt = 3 then        -- firmware ID
              txcnt <= txcnt + 1;
              tx_data_sig <= FIRMWARE_ID;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;
            elsif txcnt = 4 then        -- mirrored command
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000001";
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;
            elsif txcnt = 5 then        -- data: DAC A low
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(0),16)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;
            elsif txcnt = 6 then        -- data: DAC A high
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(0),16)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;
            elsif txcnt = 7 then        -- data: DAC B low
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(1),16)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;
            elsif txcnt = 8 then        -- data: DAC B high
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(1),16)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;
            elsif txcnt = 9 then        -- data: DAC C low
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(2),16)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;
            elsif txcnt = 10 then        -- data: DAC C high
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(2),16)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;
            elsif txcnt = 11 then        -- data: DAC D low
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(3),16)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;
            elsif txcnt = 12 then        -- data: DAC D high
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(3),16)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;
            elsif txcnt = 13 then        -- data: DAC E low
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(7),16)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;
            elsif txcnt = 14 then        -- data: DAC E high
              txcnt <= txcnt + 1;
              tx_data_sig <= conv_std_logic_vector(dac_array_rs485_in(7),16)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;
            elsif txcnt < ((RS485_BLOCK_WIDTH / 8) - 2) then        -- data: not used
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;
            elsif txcnt = ((RS485_BLOCK_WIDTH / 8) - 2) then        -- CRC error counter
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";  -- NOT YET IMPLEMENTED!!!
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;
            elsif txcnt = ((RS485_BLOCK_WIDTH / 8) - 1) then        -- check sum
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";  -- NOT YET IMPLEMENTED!!!
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_DAC_TRANSMIT;              
            else                        -- transmission finished
              txcnt <= 0;
              FTU_rs485_control_State <= RECEIVE;
            end if;  
          else
            tx_start_sig <= '0';
            FTU_rs485_control_State <= READ_DAC_TRANSMIT;
          end if;

        when READ_ENABLE_TRANSMIT =>
          if tx_busy_sig = '0' then
            if txcnt = 0 then           -- start delimiter
              txcnt <= txcnt + 1;
              tx_data_sig <= RS485_START_DELIM;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;
            elsif txcnt = 1 then        -- FTM address
              txcnt <= txcnt + 1;
              tx_data_sig <= FTM_ADDRESS;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;
            elsif txcnt = 2 then        -- board address
              txcnt <= txcnt + 1;
              tx_data_sig <= "00" & brd_add;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;
            elsif txcnt = 3 then        -- firmware ID
              txcnt <= txcnt + 1;
              tx_data_sig <= FIRMWARE_ID;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;
            elsif txcnt = 4 then        -- mirrored command
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000100";
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;
            elsif txcnt = 5 then        -- data: enable pattern A7-0
              txcnt <= txcnt + 1;
              tx_data_sig <= enable_array_rs485_in(0)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;
            elsif txcnt = 6 then        -- data: enable pattern A8
              txcnt <= txcnt + 1;
              tx_data_sig <= enable_array_rs485_in(0)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;
            elsif txcnt = 7 then        -- data: enable pattern B7-0
              txcnt <= txcnt + 1;
              tx_data_sig <= enable_array_rs485_in(1)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;
            elsif txcnt = 8 then        -- data: enable pattern B8
              txcnt <= txcnt + 1;
              tx_data_sig <= enable_array_rs485_in(1)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;
            elsif txcnt = 9 then        -- data: enable pattern C7-0
              txcnt <= txcnt + 1;
              tx_data_sig <= enable_array_rs485_in(2)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;
            elsif txcnt = 10 then        -- data: enable pattern C8
              txcnt <= txcnt + 1;
              tx_data_sig <= enable_array_rs485_in(2)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;
            elsif txcnt = 11 then        -- data: enable pattern D7-0
              txcnt <= txcnt + 1;
              tx_data_sig <= enable_array_rs485_in(3)(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;
            elsif txcnt = 12 then        -- data: enable pattern D8
              txcnt <= txcnt + 1;
              tx_data_sig <= enable_array_rs485_in(3)(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;
            elsif txcnt < ((RS485_BLOCK_WIDTH / 8) - 2) then        -- data: not used
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;
            elsif txcnt = ((RS485_BLOCK_WIDTH / 8) - 2) then        -- CRC error counter
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";  -- NOT YET IMPLEMENTED!!!
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;
            elsif txcnt = ((RS485_BLOCK_WIDTH / 8) - 1) then        -- check sum
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";  -- NOT YET IMPLEMENTED!!!
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;    
            else                        -- transmission finished
              txcnt <= 0;
              FTU_rs485_control_State <= RECEIVE;
            end if;  
          else
            tx_start_sig <= '0';
            FTU_rs485_control_State <= READ_ENABLE_TRANSMIT;
          end if;

        when READ_PRESCALING_TRANSMIT =>
          if tx_busy_sig = '0' then
            if txcnt = 0 then           -- start delimiter
              txcnt <= txcnt + 1;
              tx_data_sig <= RS485_START_DELIM;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_PRESCALING_TRANSMIT;
            elsif txcnt = 1 then        -- FTM address
              txcnt <= txcnt + 1;
              tx_data_sig <= FTM_ADDRESS;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_PRESCALING_TRANSMIT;
            elsif txcnt = 2 then        -- board address
              txcnt <= txcnt + 1;
              tx_data_sig <= "00" & brd_add;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_PRESCALING_TRANSMIT;
            elsif txcnt = 3 then        -- firmware ID
              txcnt <= txcnt + 1;
              tx_data_sig <= FIRMWARE_ID;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_PRESCALING_TRANSMIT;
            elsif txcnt = 4 then        -- mirrored command
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000111";
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_PRESCALING_TRANSMIT;
            elsif txcnt = 5 then        -- data: prescaling
              txcnt <= txcnt + 1;
              tx_data_sig <= prescaling_rs485_in;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_PRESCALING_TRANSMIT;
            elsif txcnt = 6 then        -- data: overflow register
              txcnt <= txcnt + 1;
              tx_data_sig <= overflow_array_rs485_in;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_PRESCALING_TRANSMIT;
            elsif txcnt < ((RS485_BLOCK_WIDTH / 8) - 2) then        -- data: not used
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_PRESCALING_TRANSMIT;
            elsif txcnt = ((RS485_BLOCK_WIDTH / 8) - 2) then        -- CRC error counter
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";  -- NOT YET IMPLEMENTED!!!
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_PRESCALING_TRANSMIT;
            elsif txcnt = ((RS485_BLOCK_WIDTH / 8) - 1) then        -- check sum
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";  -- NOT YET IMPLEMENTED!!!
              tx_start_sig <= '1';
              FTU_rs485_control_State <= READ_PRESCALING_TRANSMIT;
            else                        -- transmission finished
              txcnt <= 0;
              FTU_rs485_control_State <= RECEIVE;
            end if;  
          else
            tx_start_sig <= '0';
            FTU_rs485_control_State <= READ_PRESCALING_TRANSMIT;
          end if;

        when PING_PONG_TRANSMIT =>
          if tx_busy_sig = '0' then
            if txcnt = 0 then           -- start delimiter
              txcnt <= txcnt + 1;
              tx_data_sig <= RS485_START_DELIM;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= PING_PONG_TRANSMIT;
            elsif txcnt = 1 then        -- FTM address
              txcnt <= txcnt + 1;
              tx_data_sig <= FTM_ADDRESS;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= PING_PONG_TRANSMIT;
            elsif txcnt = 2 then        -- board address
              txcnt <= txcnt + 1;
              tx_data_sig <= "00" & brd_add;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= PING_PONG_TRANSMIT;
            elsif txcnt = 3 then        -- firmware ID
              txcnt <= txcnt + 1;
              tx_data_sig <= FIRMWARE_ID;
              tx_start_sig <= '1';
              FTU_rs485_control_State <= PING_PONG_TRANSMIT;
            elsif txcnt = 4 then        -- mirrored command
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000101";
              tx_start_sig <= '1';
              FTU_rs485_control_State <= PING_PONG_TRANSMIT;
            elsif txcnt = 5 then        -- data: device DNA
              txcnt <= txcnt + 1;
              tx_data_sig <= dna(7 downto 0);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= PING_PONG_TRANSMIT;
            elsif txcnt = 6 then        -- data: device DNA
              txcnt <= txcnt + 1;
              tx_data_sig <= dna(15 downto 8);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= PING_PONG_TRANSMIT;
            elsif txcnt = 7 then        -- data: device DNA
              txcnt <= txcnt + 1;
              tx_data_sig <= dna(23 downto 16);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= PING_PONG_TRANSMIT;
            elsif txcnt = 8 then        -- data: device DNA
              txcnt <= txcnt + 1;
              tx_data_sig <= dna(31 downto 24);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= PING_PONG_TRANSMIT;
            elsif txcnt = 9 then        -- data: device DNA
              txcnt <= txcnt + 1;
              tx_data_sig <= dna(39 downto 32);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= PING_PONG_TRANSMIT;
            elsif txcnt = 10 then        -- data: device DNA
              txcnt <= txcnt + 1;
              tx_data_sig <= dna(47 downto 40);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= PING_PONG_TRANSMIT;
            elsif txcnt = 11 then       -- data: device DNA
              txcnt <= txcnt + 1;
              tx_data_sig <= dna(55 downto 48);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= PING_PONG_TRANSMIT;
            elsif txcnt = 12 then       -- data: device DNA
              txcnt <= txcnt + 1;
              tx_data_sig <= dna(63 downto 56);
              tx_start_sig <= '1';
              FTU_rs485_control_State <= PING_PONG_TRANSMIT;
            elsif txcnt < ((RS485_BLOCK_WIDTH / 8) - 2) then        -- data: not used
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";
              tx_start_sig <= '1';
              FTU_rs485_control_State <= PING_PONG_TRANSMIT;
            elsif txcnt = ((RS485_BLOCK_WIDTH / 8) - 2) then        -- CRC error counter
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";  -- NOT YET IMPLEMENTED!!!
              tx_start_sig <= '1';
              FTU_rs485_control_State <= PING_PONG_TRANSMIT;
            elsif txcnt = ((RS485_BLOCK_WIDTH / 8) - 1) then        -- check sum
              txcnt <= txcnt + 1;
              tx_data_sig <= "00000000";  -- NOT YET IMPLEMENTED!!!
              tx_start_sig <= '1';
              FTU_rs485_control_State <= PING_PONG_TRANSMIT;
            else                        -- transmission finished
              txcnt <= 0;
              FTU_rs485_control_State <= RECEIVE;
            end if;  
          else
            tx_start_sig <= '0';
            FTU_rs485_control_State <= PING_PONG_TRANSMIT;
          end if;
          
      end case;
    end if;
  end process FTU_rs485_control_FSM;

end Behavioral;

