]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/commitdiff
Implemented initial version of LXPWR receiver FSM based on transmitter.
authorPavel Pisa <ppisa@pikron.com>
Sun, 15 Jun 2014 21:24:10 +0000 (23:24 +0200)
committerPavel Pisa <ppisa@pikron.com>
Sun, 15 Jun 2014 21:24:10 +0000 (23:24 +0200)
The basic implementation does not check CRC for now.

Signed-off-by: Pavel Pisa <ppisa@pikron.com>
hw/bus_lxmaster.vhd
hw/lx_crosdom_ser_fifo.vhd [new file with mode: 0644]
hw/lx_rocon_pkg.vhd
hw/lx_rocon_top.prj
hw/lx_rocon_top.vhd
hw/lxmaster_receiver.vhd [new file with mode: 0644]

index 42019846f32abff33d60e6dcb711ca5e7a5bbd97..cb0b3409442970da98c2a886c58fcec37310ee06 100644 (file)
@@ -37,6 +37,13 @@ architecture Behavioral of bus_lxmaster is
        signal mem_trans_out_s      : std_logic;
        signal mem_trans_out_r      : std_logic;
        --
+       signal mem_recv_en_s        : std_logic;
+       signal mem_recv_bls_s       : std_logic_vector(1 downto 0);
+       signal mem_recv_addr_s      : std_logic_vector(8 downto 0);
+       signal mem_recv_data_s      : std_logic_vector(15 downto 0);
+       signal mem_recv_out_s       : std_logic;
+       signal mem_recv_out_r       : std_logic;
+       --
        signal state_o_s            : std_logic_vector(1 downto 0);
        signal state_o_r            : std_logic_vector(1 downto 0);
        --
@@ -52,6 +59,10 @@ architecture Behavioral of bus_lxmaster is
        signal register_trans_wr_s  : std_logic;
        signal wdog_trans_in_s      : std_logic;
        signal wdog_trans_wr_s      : std_logic;
+       --
+       signal register_recv_in_s   : std_logic;
+       signal register_recv_out_s  : std_logic_vector(1 downto 0);
+       signal register_recv_wr_s   : std_logic;
 
 begin
 
@@ -80,21 +91,50 @@ master_transmitter: lxmaster_transmitter
                mem_data_o       => mem_trans_data_s
        );
 
+master_receiver: lxmaster_receiver
+       port map
+       (
+               clk_i            => clk_i,
+               reset_i          => reset_s,
+               -- Receiver serial data
+               clock_i          => clock_i,
+               miso_i           => miso_i,
+               sync_i           => sync_i,
+               -- Register
+               register_i       => register_recv_in_s,
+               register_o       => register_recv_out_s,
+               register_we_i    => register_recv_wr_s,
+               -- BRAM
+               mem_clk_i        => clk_i,
+               mem_en_i         => mem_recv_en_s,
+               mem_we_i         => mem_recv_bls_s,
+               mem_addr_i       => mem_recv_addr_s,
+               mem_data_i       => data_i,
+               mem_data_o       => mem_recv_data_s
+       );
+
        reset_s <= reset_reg_r or reset_i;
 
 wire_in:
-       process(next_ce_i, ce_s, reset_reg_r, bls_i, address_i, mem_trans_data_s, data_i, register_trans_out_s)
+       process(next_ce_i, ce_s, reset_reg_r, bls_i, address_i, mem_trans_data_s,
+               mem_recv_data_s, data_i, register_trans_out_s, register_recv_out_s)
        begin
 
                mem_trans_en_s       <= '0';
                mem_trans_out_s      <= '0';
                mem_trans_bls_s      <= (others => '0');
                mem_trans_addr_s     <= (others => '0');
+               mem_recv_en_s        <= '0';
+               mem_recv_out_s       <= '0';
+               mem_recv_bls_s       <= (others => '0');
+               mem_recv_addr_s      <= (others => '0');
                state_o_s            <= (others => '0');
                reset_reg_s          <= '0';
                reset_reg_wr_s       <= '0';
                register_trans_in_s  <= '0';
                register_trans_wr_s  <= '0';
+               register_recv_in_s   <= '0';
+               register_recv_wr_s   <= '0';
                wdog_trans_in_s      <= '0';
                wdog_trans_wr_s      <= '0';
 
@@ -106,7 +146,9 @@ wire_in:
                        -- 01 & xxxxxxxx - LX Master receiver BRAM
                        -- 10 & 00000000 - LX Master reset
                        -- 10 & 00000001 - LX Master transmitter register
-                       -- 10 & 00000010 - LX Master receiver register
+                       -- 10 & 00000010 - LX Master watchdog
+                       -- 10 & 00000011 - LX Master cycle period register
+                       -- 10 & 00000100 - LX Master receiver control register
                        if address_i(10 downto 9) = "00" then
 
                                mem_trans_addr_s    <= address_i(8 downto 0);
@@ -114,11 +156,18 @@ wire_in:
                                mem_trans_bls_s     <= bls_i;
                                mem_trans_out_s     <= '1';
 
+                       elsif address_i(10 downto 9) = "01" then
+
+                               mem_recv_addr_s     <= address_i(8 downto 0);
+                               mem_recv_en_s       <= '1';
+                               mem_recv_bls_s      <= bls_i;
+                               mem_recv_out_s      <= '1';
+
                        else
 
-                               if address_i(8 downto 2) = "0000000" then
+                               if address_i(8 downto 3) = "000000" then
 
-                                       if address_i(1 downto 0) = "00" then
+                                       if address_i(2 downto 0) = "000" then
                                                -- LX Master reset
                                                if bls_i(0) = '1' then
                                                        reset_reg_s          <= data_i(0);
@@ -128,7 +177,7 @@ wire_in:
                                                        state_o_s(0)         <= reset_reg_r;
                                                        state_o_s(1)         <= '0';
                                                end if;
-                                       elsif address_i(1 downto 0) = "01" then
+                                       elsif address_i(2 downto 0) = "001" then
                                                -- LX Master register
                                                if bls_i(0) = '1' then
                                                        register_trans_in_s  <= data_i(0);
@@ -136,11 +185,18 @@ wire_in:
                                                else
                                                        state_o_s            <= register_trans_out_s;
                                                end if;
-                                       elsif address_i(1 downto 0) = "10" then
+                                       elsif address_i(2 downto 0) = "010" then
                                                if bls_i(0) = '1' then
                                                        wdog_trans_in_s      <= data_i(0);
                                                        wdog_trans_wr_s      <= '1';
                                                end if;
+                                       elsif address_i(2 downto 0) = "100" then
+                                               if bls_i(0) = '1' then
+                                                       register_recv_in_s  <= data_i(0);
+                                                       register_recv_wr_s  <= '1';
+                                               else
+                                                       state_o_s            <= register_recv_out_s;
+                                               end if;
                                        end if;
 
                                end if;
@@ -150,7 +206,8 @@ wire_in:
        end process;
 
 wire_out:
-       process(ce_s, mem_trans_data_s, mem_trans_out_r, state_o_r)
+       process(ce_s, mem_trans_data_s, mem_trans_out_r, 
+               mem_recv_data_s, mem_recv_out_r, state_o_r)
        begin
 
                data_o <= (others => '0');
@@ -158,6 +215,8 @@ wire_out:
                if ce_s = '1' then
                        if mem_trans_out_r = '1' then
                                data_o             <= mem_trans_data_s;
+                       elsif mem_recv_out_r = '1' then
+                               data_o             <= mem_recv_data_s;
                        else
                                data_o(1 downto 0) <= state_o_r;
                        end if;
@@ -171,6 +230,7 @@ update:
                wait until clk_i'event and clk_i= '1';
                ce_s            <= next_ce_i;
                mem_trans_out_r <= mem_trans_out_s;
+               mem_recv_out_r  <= mem_recv_out_s;
                state_o_r       <= state_o_s;
 
                if reset_i = '1' then
diff --git a/hw/lx_crosdom_ser_fifo.vhd b/hw/lx_crosdom_ser_fifo.vhd
new file mode 100644 (file)
index 0000000..3330c53
--- /dev/null
@@ -0,0 +1,120 @@
+-- Clock Cross Domain Synchronization Elastic Buffer/FIFO
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+use work.util_pkg.all;
+use work.lx_rocon_pkg.all;
+
+entity lx_crosdom_ser_fifo is
+generic
+(
+       fifo_len_g   : positive := 8;
+       sync_adj_g   : integer := 0
+);
+port
+(
+       -- Asynchronous clock domain interface
+       acd_clock_i  : in std_logic;
+       acd_miso_i   : in std_logic;
+       acd_sync_i   : in std_logic;
+       -- Clock
+       clk_i        : in std_logic;
+       reset_i      : in std_logic;
+       -- Output synchronous with clk_i
+       miso_o       : out std_logic;
+       sync_o       : out std_logic;
+       data_ready_o : out std_logic
+);
+end lx_crosdom_ser_fifo;
+
+architecture Behavioral of lx_crosdom_ser_fifo is
+       signal fifo_bits_s     : std_logic_vector(0 to fifo_len_g - 1);
+       signal fifo_bits_r     : std_logic_vector(0 to fifo_len_g - 1);
+
+       signal acd_miso_r      : std_logic;
+       signal acd_sync_r      : std_logic;
+       signal acd_sync_prev_s : std_logic;
+       signal acd_sync_prev_r : std_logic;
+
+       signal acd_in_loc_s    : natural range 0 to fifo_len_g - 1;
+       signal acd_in_loc_r    : natural range 0 to fifo_len_g - 1;
+
+       signal out_loc_s       : natural range 0 to fifo_len_g - 1;
+       signal out_loc_r       : natural range 0 to fifo_len_g - 1;
+
+       signal out_sync_s      : std_logic_vector(0 to fifo_len_g / 2 - 1);
+       signal out_sync_r      : std_logic_vector(0 to fifo_len_g / 2 - 1);
+
+       signal out_miso_s      : std_logic;
+
+  attribute REGISTER_DUPLICATION : string;
+       attribute REGISTER_DUPLICATION of fifo_bits_s : signal is "NO";
+       attribute REGISTER_DUPLICATION of fifo_bits_r : signal is "NO";
+       attribute REGISTER_DUPLICATION of acd_sync_r : signal is "NO";
+       attribute REGISTER_DUPLICATION of out_sync_s : signal is "NO";
+       attribute REGISTER_DUPLICATION of out_sync_r : signal is "NO";
+
+begin
+       sync_o <= out_sync_r(max(-sync_adj_g, 0));
+
+       data_ready_o <= '0';
+
+acd_logic:
+       process (acd_miso_r, acd_sync_r, acd_sync_prev_r, acd_in_loc_r, fifo_bits_r)
+       begin
+               acd_sync_prev_s <= acd_sync_r;
+               fifo_bits_s <= fifo_bits_r;
+               if (acd_sync_r = '1') and (acd_sync_prev_r = '0') then
+                       acd_in_loc_s <= 0;
+                       fifo_bits_s(0) <= acd_miso_r;
+               else
+                       fifo_bits_s(acd_in_loc_r) <= acd_miso_r;
+                       if acd_in_loc_r /= fifo_len_g - 1 then
+                               acd_in_loc_s <= acd_in_loc_r + 1;
+                       else
+                               acd_in_loc_s <= 0;
+                       end if;
+               end if;
+       end process;
+
+acd_update:
+       process
+       begin
+               wait until acd_clock_i'event and acd_clock_i = '1';
+
+               acd_miso_r <= acd_miso_i;
+               acd_sync_r <= acd_sync_i;
+               acd_sync_prev_r <= acd_sync_prev_s;
+               acd_in_loc_r <= acd_in_loc_s;
+               fifo_bits_r <= fifo_bits_s;
+       end process;
+
+sync_logic:
+       process (fifo_bits_r, out_loc_r, out_sync_r, acd_sync_r)
+       begin
+               out_sync_s <= out_sync_r(1 to out_sync_r'length - 1 ) & acd_sync_r;
+               if out_sync_r(max(sync_adj_g, 0)) = '0' then
+                       out_loc_s <= 0;
+                       out_miso_s <= '0';
+               else
+                       out_miso_s <= fifo_bits_r(out_loc_r);
+                       if out_loc_r /= fifo_len_g - 1 then
+                               out_loc_s <= out_loc_r + 1;
+                       else
+                               out_loc_s <= 0;
+                       end if;
+               end if;
+       end process;
+
+sync_update:
+       process
+       begin
+               wait until clk_i'event and clk_i = '1';
+
+               out_loc_r <= out_loc_s;
+               miso_o <= out_miso_s;
+               out_sync_r <= out_sync_s;
+       end process;
+
+end Behavioral;
index f81465295c1d673a5baacb91b30f30b594433d2a..4eea2817f6d8b28bbcb60d19ee365db5a990b903 100644 (file)
@@ -157,7 +157,7 @@ package lx_rocon_pkg is
   );
        end component;
 
-       -- LX Master
+       -- LX Master transmitter
        component lxmaster_transmitter
        port
        (
@@ -184,6 +184,53 @@ package lx_rocon_pkg is
        );
        end component;
 
+       -- LX Master receiver
+       component lxmaster_receiver
+       port
+       (
+               clk_i             : in std_logic;
+               reset_i           : in std_logic;
+               -- Transmision
+               clock_i           : in std_logic;
+               miso_i            : in std_logic;
+               sync_i            : in std_logic;
+               -- Register
+               register_i        : in std_logic;
+               register_o        : out std_logic_vector(1 downto 0);
+               register_we_i     : in std_logic;
+               -- BRAM access
+               mem_clk_i         : in std_logic;
+               mem_en_i          : in std_logic;
+               mem_we_i          : in std_logic_vector(1 downto 0);
+               mem_addr_i        : in std_logic_vector(8 downto 0);
+               mem_data_i        : in std_logic_vector(15 downto 0);
+               mem_data_o        : out std_logic_vector(15 downto 0)
+       );
+       end component;
+
+       -- Clock Cross Domain Synchronization Elastic Buffer/FIFO
+       component lx_crosdom_ser_fifo
+       generic
+       (
+               fifo_len_g   : positive := 8;
+               sync_adj_g   : integer := 0
+       );
+       port
+       (
+               -- Asynchronous clock domain interface
+               acd_clock_i  : in std_logic;
+               acd_miso_i   : in std_logic;
+               acd_sync_i   : in std_logic;
+               -- Clock
+               clk_i        : in std_logic;
+               reset_i      : in std_logic;
+               -- Output synchronous with clk_i
+               miso_o       : out std_logic;
+               sync_o       : out std_logic;
+               data_ready_o : out std_logic
+       );
+       end component;
+
        --------------------------------------------------------------------------------
        -- TUMBL
        --------------------------------------------------------------------------------
index 14ca015f58532b6644bff188750fddda32e93bc2..ab24c6bb9c0cf7814ba7c039e4bc9ba8de87db63 100644 (file)
@@ -16,6 +16,8 @@ vhdl work "irc_proc_inc.vhd"
 vhdl work "crc.vhd"
 vhdl work "measurement_register.vhd"
 vhdl work "lxmaster_transmitter.vhd"
+vhdl work "lxmaster_receiver.vhd"
+vhdl work "lx_crosdom_ser_fifo.vhd"
 vhdl work "lx-rocon_tumbl/lx_rocon_tumbl.vhd"
 vhdl work "irc_reader.vhd"
 vhdl work "irc_proc_main.vhd"
index 8abd3a79f7824ea1432c2a349b1ac912ec656645..cc99e404b3484dee3655201fb92f52d80cc72544 100644 (file)
@@ -166,6 +166,10 @@ architecture Behavioral of lx_rocon_top is
        signal tumbl_xmemb_i_s     : DMEMB2CORE_Type;
        signal tumbl_xmemb_sel_s   : std_logic;
 
+       -- signal s0   : std_logic;
+       -- signal s1   : std_logic;
+       -- signal s2   : std_logic;
+
        -- XST attributes
        attribute REGISTER_DUPLICATION : string;
        attribute REGISTER_DUPLICATION of rd : signal is "NO";
@@ -282,8 +286,21 @@ memory_bus_lxmaster: bus_lxmaster
                clock_o        => s1_clk_out,
                mosi_o         => s1_mosi,
                sync_o         => s1_sync_out
+               --
+               -- clock_i        => s0,
+               -- miso_i         => s1,
+               -- sync_i         => not s2,
+               --
+               -- clock_o        => s0,
+               -- mosi_o         => s1,
+               -- sync_o         => s2
        );
 
+       -- s1_clk_out      <= s0;
+       -- s1_mosi         <= s1;
+       -- s1_sync_out     <= s2;
+
+
 -- Reset
 dff_reset: dff2
        port map
diff --git a/hw/lxmaster_receiver.vhd b/hw/lxmaster_receiver.vhd
new file mode 100644 (file)
index 0000000..8be3b62
--- /dev/null
@@ -0,0 +1,373 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+use work.util_pkg.all;
+use work.lx_rocon_pkg.all;
+
+-- LX Master (Transmitter)
+entity lxmaster_receiver is
+       port
+       (
+               clk_i             : in std_logic;
+               reset_i           : in std_logic;
+               -- Transmision
+               clock_i           : in std_logic;
+               miso_i            : in std_logic;
+               sync_i            : in std_logic;
+               -- Register
+               register_i        : in std_logic;
+               register_o        : out std_logic_vector(1 downto 0);
+               register_we_i     : in std_logic;
+               -- BRAM access
+               mem_clk_i         : in std_logic;
+               mem_en_i          : in std_logic;
+               mem_we_i          : in std_logic_vector(1 downto 0);
+               mem_addr_i        : in std_logic_vector(8 downto 0);
+               mem_data_i        : in std_logic_vector(15 downto 0);
+               mem_data_o        : out std_logic_vector(15 downto 0)
+       );
+end lxmaster_receiver;
+
+architecture Behavioral of lxmaster_receiver is
+
+       -- Types
+       type state_t is (ST_INIT, ST_READY, ST_XFER, ST_CRC, ST_END);
+       constant msg_max_count_c        : positive := 8;
+       -- RAM Access
+       signal ram_en_s                 : std_logic;
+       signal ram_we_s                 : std_logic_vector(1 downto 0);
+       signal ram_rst_s                : std_logic;
+       signal ram_addr_s               : std_logic_vector(8 downto 0);
+       signal ram_addr_r               : std_logic_vector(8 downto 0);
+       signal ram_data_o_s             : std_logic_vector(15 downto 0);
+       signal ram_data_i_s             : std_logic_vector(15 downto 0);
+       signal inc_ram_addr_s           : std_logic;
+       signal inc_ram_addr_r           : std_logic;
+       -- State
+       signal lxmaster_state_s         : state_t;
+       signal lxmaster_state_r         : state_t;
+       signal lxmaster_last_word_s     : std_logic;
+       signal lxmaster_last_word_r     : std_logic;
+       -- Data
+       signal lxmaster_num_data_s      : std_logic_vector(7 downto 0); -- If 0 then the peripheral is not active this cycle
+       signal lxmaster_num_data_r      : std_logic_vector(7 downto 0);
+       signal lxmaster_data_counter_s  : natural range 0 to 15;
+       signal lxmaster_data_counter_r  : natural range 0 to 15;
+       -- Receiption
+       signal lxmaster_frame_start_s   : std_logic;
+       signal lxmaster_sync_s          : std_logic;
+       signal lxmaster_sync_r          : std_logic;
+       signal lxmaster_sync_last_bit_s : std_logic;
+       signal lxmaster_sync_last_bit_r : std_logic;
+       signal miso_s                   : std_logic;
+       signal sync_s                   : std_logic;
+       signal prev_sync_s              : std_logic;
+       signal prev_sync_r              : std_logic;
+       signal data_ready_s             : std_logic;
+       signal received_data_s          : std_logic_vector(15 downto 0);
+       signal received_data_r          : std_logic_vector(15 downto 0);
+       -- Counters
+       signal lxmaster_msg_counter_s   : natural range 0 to (msg_max_count_c-1);
+       signal lxmaster_msg_counter_r   : natural range 0 to (msg_max_count_c-1);
+       -- CRC
+       signal lxmaster_crc_data_s      : std_logic;
+       signal lxmaster_crc_reset_s     : std_logic;
+       signal lxmaster_crc_out_s       : std_logic_vector(7 downto 0);
+       signal lxmaster_crc_reg_s       : std_logic_vector(7 downto 0);
+       signal lxmaster_crc_reg_r       : std_logic_vector(7 downto 0);
+       -- RAM reset
+       signal lxmaster_ram_reset_s     : std_logic;
+       -- Register
+       -- Bit 0: Transmitter - use first or second buffer (I/O)
+       signal lxmaster_register_in_s   : std_logic;
+       signal lxmaster_register_out_s  : std_logic_vector(1 downto 0);
+
+begin
+
+       -- Directly route out some signals
+       lxmaster_frame_start_s <= '1' when (sync_s = '1') and (prev_sync_r = '0') else '0';
+
+       -- CRC
+       lxmaster_crc_reg_s   <= '0' & lxmaster_crc_reg_r(7 downto 1) when lxmaster_state_r = ST_CRC else lxmaster_crc_out_s;
+       lxmaster_crc_data_s  <= '1' when lxmaster_state_r = ST_CRC else received_data_r(0);
+       lxmaster_crc_reset_s <= '1' when lxmaster_state_r /= ST_XFER or reset_i = '1' else '0';
+
+       -- Register
+       register_o           <= lxmaster_register_out_s;
+
+ram: xilinx_dualport_bram
+       generic map
+       (
+               we_width      => 2,
+               byte_width    => 8,
+               address_width => 9,
+               port_a_type   => WRITE_FIRST,
+               port_b_type   => READ_FIRST
+       )
+       port map
+       (
+               -- Internal
+               clka  => clk_i,
+               rsta  => ram_rst_s,
+               ena   => ram_en_s,
+               wea   => ram_we_s,
+               addra => ram_addr_s,
+               dina  => ram_data_i_s,
+               douta => ram_data_o_s,
+               -- External
+               clkb  => mem_clk_i,
+               rstb  => '0',
+               enb   => mem_en_i,
+               web   => mem_we_i,
+               addrb => mem_addr_i,
+               dinb  => mem_data_i,
+               doutb => mem_data_o
+       );
+
+crc_out: crc
+       port map
+       (
+               clk_i   => clk_i,
+               reset_i => lxmaster_crc_reset_s,
+               input_i => lxmaster_crc_data_s,
+               crc_o   => lxmaster_crc_out_s
+       );
+
+       ram_rst_s <= reset_i or lxmaster_ram_reset_s;
+
+crosdom_ser_fifo: lx_crosdom_ser_fifo
+       generic map
+       (
+               sync_adj_g   => -1
+       )
+       port map
+       (
+               -- Asynchronous clock domain interface
+               acd_clock_i  => clock_i,
+               acd_miso_i   => miso_i,
+               acd_sync_i   => sync_i,
+               -- Clock
+               clk_i        => clk_i,
+               reset_i      => reset_i,
+               -- Output synchronous with clk_i
+               miso_o       => miso_s,
+               sync_o       => sync_s,
+               data_ready_o => data_ready_s -- Not used for now
+       );
+
+-- Update
+-- TODO: Maybe some exception handling (overflows etc.)
+transmitter_update:
+       process (ram_data_o_s, ram_addr_r, inc_ram_addr_r, lxmaster_state_r, lxmaster_num_data_r, lxmaster_msg_counter_r,
+                lxmaster_last_word_r, lxmaster_data_counter_r, reset_i, lxmaster_frame_start_s, lxmaster_register_in_s,
+                 sync_s, miso_s, prev_sync_r, received_data_r)
+               variable ram_addr_v : std_logic_vector(8 downto 0);
+       begin
+
+               -- Defaults
+               lxmaster_ram_reset_s               <= '0';
+               lxmaster_sync_last_bit_s           <= '0';
+               -- Defaults of state variables (no change)
+               ram_addr_s                         <= ram_addr_r;
+               inc_ram_addr_s                     <= '0';
+               lxmaster_state_s                   <= lxmaster_state_r;
+               lxmaster_data_counter_s            <= lxmaster_data_counter_r;
+               lxmaster_num_data_s                <= lxmaster_num_data_r;
+               lxmaster_msg_counter_s             <= lxmaster_msg_counter_r;
+               lxmaster_last_word_s               <= lxmaster_last_word_r;
+
+               prev_sync_s                        <=  sync_s;
+               ram_we_s                           <= "00";
+
+               ram_data_i_s                       <= received_data_r;
+               received_data_s <= miso_s & received_data_r(received_data_r'length - 1 downto 1);
+
+               if reset_i = '1' then
+                       lxmaster_num_data_s              <= x"00";
+                       lxmaster_state_s                 <= ST_END;
+                       lxmaster_sync_s                  <= '0';
+                       lxmaster_last_word_s             <= '0';
+                       --
+                       ram_addr_s                       <= '0' & x"00";
+                       ram_en_s                         <= '0';
+                       --
+                       lxmaster_ram_reset_s             <= '1';
+
+               else
+
+                       -- OK, we are enabled, default values
+                       lxmaster_sync_s                  <= '0'; -- Not transferring
+                       ram_en_s                         <= '0'; -- Not reading
+
+                       case lxmaster_state_r is
+
+                               when ST_INIT =>
+                                       -- We just read number of commands
+                                       if ram_data_o_s(7 downto 0) = x"00" then
+                                               lxmaster_state_s           <= ST_END; --Nothing
+                                       else
+                                               lxmaster_state_s           <= ST_READY; -- Make next read init the transfer
+                                               ram_addr_v                   := ram_addr_r(8) & ram_data_o_s(15 downto 8); -- Update address
+                                               ram_addr_s                   <= ram_addr_v;
+                                               lxmaster_num_data_s          <= std_logic_vector(unsigned(ram_addr_v(7 downto 0)) + unsigned(ram_data_o_s(7 downto 0)));
+                                               ram_en_s                     <= '1'; -- Read
+                                       end if;
+
+                                       -- Prepare message counter
+                                       lxmaster_msg_counter_s       <= 0;
+
+                               when ST_READY =>
+                                       -- We are ready to begin transferring
+                                       lxmaster_sync_s              <= '1'; -- Transferring data next cycle
+                                       lxmaster_data_counter_s      <= 0; -- Reset counter
+                                       lxmaster_state_s             <= ST_XFER; --Go to transfer loop
+
+                               when ST_XFER =>
+                                       lxmaster_sync_s              <= '1'; -- Transferring data next cycle
+
+                                       if inc_ram_addr_r = '1' then
+                                               -- Update address if second and other loop
+                                               ram_addr_s  <= ram_addr_r(8) & (ram_addr_r(7 downto 0) + 1);
+                                       end if;
+
+                                       if lxmaster_data_counter_r = 14 then
+                                               lxmaster_data_counter_s    <= lxmaster_data_counter_r + 1; -- Increment
+
+                                               if (ram_addr_r(7 downto 0) + 1) /= lxmaster_num_data_r then
+                                                       lxmaster_last_word_s       <= '0';
+                                               else
+                                                       lxmaster_last_word_s       <= '1';
+                                               end if;
+
+                                       elsif lxmaster_data_counter_r = 15 then
+                                               -- At 15th bit, we either stop if ram_addr_r equals lxmaster_num_data_r
+                                               if lxmaster_last_word_r = '1' then
+                                                       lxmaster_state_s         <= ST_CRC;
+                                                       lxmaster_data_counter_s  <= 0;
+                                               else
+                                                       lxmaster_data_counter_s  <= 0;
+                                               end if;
+
+                                               ram_we_s                   <= "11";
+                                               ram_en_s                   <= '1';
+                                               inc_ram_addr_s             <= '1';
+                                       else
+                                               -- Increment
+                                               lxmaster_data_counter_s    <= lxmaster_data_counter_r + 1;
+                                       end if;
+
+                               when ST_CRC =>
+
+                                       -- Check if this is last command, first read one more
+                                       if lxmaster_data_counter_r = 0 then
+                                               if lxmaster_msg_counter_r = (msg_max_count_c - 1) then
+                                                       lxmaster_ram_reset_s     <= '1'; -- Make sure we read 0 if we are on the last message
+                                               else
+                                                       lxmaster_msg_counter_s  <= lxmaster_msg_counter_r + 1;
+                                               end if;
+
+                                               ram_addr_s                 <= ram_addr_r(8) & std_logic_vector(to_unsigned(lxmaster_msg_counter_r + 1, ram_addr_r'length - 1)); -- Update address
+                                               ram_en_s                   <= '1'; -- Read
+
+                                       elsif lxmaster_data_counter_r = 1 then
+
+                                               if ram_data_o_s(15 downto 8) >= msg_max_count_c then -- Need to read first command, make sure it's valid
+                                                       ram_addr_v               := ram_addr_r(8) & ram_data_o_s(15 downto 8); -- Update address
+                                                       ram_addr_s               <= ram_addr_v;
+                                                       lxmaster_num_data_s      <= std_logic_vector(unsigned(ram_addr_v(7 downto 0)) + unsigned(ram_data_o_s(7 downto 0)));
+                                                       ram_en_s                 <= '1'; -- Read
+                                               else
+                                                       lxmaster_num_data_s      <= x"00"; -- Signalize termination
+                                               end if;
+
+                                       end if;
+
+                                       if lxmaster_data_counter_r = 7 then -- Ending
+                                               lxmaster_data_counter_s    <= 0;
+
+                                               if lxmaster_num_data_r = x"00" then
+                                                       lxmaster_state_s         <= ST_END; -- Last command
+                                               else
+                                                       -- Begin transmission of next data
+                                                       lxmaster_sync_s          <= '1'; -- Transferring data next cycle
+                                                       lxmaster_data_counter_s  <= 0; -- Reset counter
+                                                       lxmaster_state_s         <= ST_XFER; --Go to transfer loop
+                                               end if;
+
+                                       else
+                                               -- Sync goes inactive to signalize termination if we're on last message
+                                               if lxmaster_data_counter_r /= 6 or lxmaster_num_data_r /= x"00" then
+                                                       lxmaster_sync_s          <= '1';
+                                               else
+                                                 lxmaster_sync_last_bit_s <= '1';
+                                               end if;
+
+                                               lxmaster_data_counter_s    <= lxmaster_data_counter_r + 1; -- Increment
+                                       end if;
+
+                               when ST_END =>
+                                       if lxmaster_frame_start_s = '1' then
+                                               -- Initialize first step
+                                               lxmaster_state_s           <= ST_INIT;
+                                               ram_addr_s                 <= lxmaster_register_in_s & x"00";
+                                               ram_en_s                   <= '1';
+                                       end if;
+
+                       end case;
+
+               end if;
+
+       end process;
+
+-- This function toggles outputs directly, make sure the outputs
+-- are updated with clock to minimize phase.
+state:
+       process
+       begin
+
+               wait until clk_i'event and clk_i = '1';
+
+               -- State update
+               ram_addr_r                     <= ram_addr_s;
+               inc_ram_addr_r                 <= inc_ram_addr_s;
+               lxmaster_state_r               <= lxmaster_state_s;
+               lxmaster_data_counter_r        <= lxmaster_data_counter_s;
+               lxmaster_num_data_r            <= lxmaster_num_data_s;
+               lxmaster_crc_reg_r             <= lxmaster_crc_reg_s;
+               lxmaster_msg_counter_r         <= lxmaster_msg_counter_s;
+               lxmaster_last_word_r           <= lxmaster_last_word_s;
+
+               -- Increment counter
+               if reset_i = '1' then
+
+                       lxmaster_register_in_s       <= '0';
+                       lxmaster_register_out_s      <= (others => '0');
+                       lxmaster_last_word_r         <= '1';
+
+               else
+
+                       if register_we_i = '1' then
+                               lxmaster_register_in_s     <= register_i;
+                       end if;
+
+                       if lxmaster_frame_start_s = '1' then
+                               lxmaster_register_out_s(0) <= lxmaster_register_in_s;
+                       end if;
+
+                       if lxmaster_state_s = ST_END then
+                               lxmaster_register_out_s(1)  <= '0';
+                       else
+                               lxmaster_register_out_s(1)  <= '1';
+                       end if;
+               end if;
+
+               lxmaster_sync_r                 <= lxmaster_sync_s;
+               lxmaster_sync_last_bit_r        <= lxmaster_sync_last_bit_s;
+
+               prev_sync_r <= prev_sync_s;
+               received_data_r <= received_data_s;
+
+       end process;
+
+end Behavioral;