]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blobdiff - hw/bus_lxmaster.vhd
Remove next_ prefix from chip selects/clock enables to reflect real phase.
[fpga/lx-cpu1/lx-rocon.git] / hw / bus_lxmaster.vhd
index feb2c859a6c1c59584d0d07c86db3b1f38456629..cdb3e11a30d16c16991127b346b7f0b1f8b8faae 100644 (file)
@@ -12,11 +12,13 @@ entity bus_lxmaster is
                reset_i      : in std_logic;
                -- Data bus
                address_i    : in std_logic_vector(10 downto 0);
-               next_ce_i    : in std_logic;
+               ce_i         : in std_logic;
                data_i       : in std_logic_vector(15 downto 0);
                data_o       : out std_logic_vector(15 downto 0);
                --
                bls_i        : in std_logic_vector(1 downto 0);
+               --
+               rx_done_o    : out std_logic;
                -- Signals for LX Master
                clock_i      : in std_logic;
                miso_i       : in std_logic;
@@ -30,6 +32,10 @@ end bus_lxmaster;
 
 architecture Behavioral of bus_lxmaster is
 
+       constant cycle_cnt_width_c  : natural := 12; -- number of bits
+       constant rx_done_div_width_c : natural := 5; -- number of bits
+       constant rx_done_cnt_width_c : natural := 5; -- number of bits
+
        signal mem_trans_en_s       : std_logic;
        signal mem_trans_bls_s      : std_logic_vector(1 downto 0);
        signal mem_trans_addr_s     : std_logic_vector(8 downto 0);
@@ -37,23 +43,47 @@ architecture Behavioral of bus_lxmaster is
        signal mem_trans_out_s      : std_logic;
        signal mem_trans_out_r      : std_logic;
        --
-       signal state_o_s            : std_logic;
-       signal state_o_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(15 downto 0);
+       signal state_o_r            : std_logic_vector(15 downto 0);
        --
        signal reset_reg_s          : std_logic;
        signal reset_reg_r          : std_logic;
        signal reset_reg_wr_s       : std_logic;
        --
        signal reset_s              : std_logic;
-       signal ce_s                 : std_logic;
+       signal ce_r                 : std_logic;
        --
        signal register_trans_in_s  : std_logic;
-       signal register_trans_out_s : std_logic;
+       signal register_trans_out_s : std_logic_vector(1 downto 0);
        signal register_trans_wr_s  : std_logic;
-
+       signal register_cycle_in_s  : std_logic_vector(cycle_cnt_width_c-1 downto 0);
+       signal register_cycle_out_s : std_logic_vector(cycle_cnt_width_c-1 downto 0);
+       signal register_cycle_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;
+       signal rx_done_s            : std_logic;
+       signal rx_done_ratio_s      : std_logic_vector(rx_done_div_width_c-1 downto 0);
+       signal rx_done_ratio_r      : std_logic_vector(rx_done_div_width_c-1 downto 0);
+       signal rx_done_ratio_wr_s   : std_logic;
+       signal rx_done_cnt_r        : natural range 0 to (2**rx_done_cnt_width_c - 1);
 begin
 
 master_transmitter: lxmaster_transmitter
+       generic map
+       (
+               cycle_cnt_width_g => cycle_cnt_width_c
+       )
        port map
        (
                clk_i            => clk_i,
@@ -66,6 +96,13 @@ master_transmitter: lxmaster_transmitter
                register_i       => register_trans_in_s,
                register_o       => register_trans_out_s,
                register_we_i    => register_trans_wr_s,
+               -- Cycle period
+               cycle_reg_i      => register_cycle_in_s,
+               cycle_reg_o      => register_cycle_out_s,
+               cycle_reg_we_i   => register_cycle_wr_s,
+               -- Watchdog
+               wdog_i           => wdog_trans_in_s,
+               wdog_we_i        => wdog_trans_wr_s,
                -- BRAM
                mem_clk_i        => clk_i,
                mem_en_i         => mem_trans_en_s,
@@ -75,32 +112,85 @@ 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,
+               -- Receive done pulse
+               rx_done_o        => rx_done_s,
+               -- 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
+       );
+
+rx_done_divider : cnt_div
+       generic map (
+               cnt_width_g      => rx_done_div_width_c
+       )
+       port map
+       (
+               clk_i            => clk_i,
+               en_i             => rx_done_s,
+               reset_i          => reset_s,
+               ratio_i          => rx_done_ratio_r,
+               q_out_o          => rx_done_o
+       );
 
        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(ce_i, ce_r, 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,
+               register_cycle_out_s, rx_done_ratio_r, rx_done_cnt_r)
        begin
 
                mem_trans_en_s       <= '0';
                mem_trans_out_s      <= '0';
                mem_trans_bls_s      <= (others => '0');
                mem_trans_addr_s     <= (others => '0');
-               state_o_s            <= '0';
-               register_trans_wr_s  <= '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_cycle_in_s  <= (others => '0');
+               register_cycle_wr_s  <= '0';
+               register_recv_in_s   <= '0';
+               register_recv_wr_s   <= '0';
+               wdog_trans_in_s      <= '0';
+               wdog_trans_wr_s      <= '0';
+               rx_done_ratio_wr_s   <= '0';
+               rx_done_ratio_s      <= rx_done_ratio_r;
 
                -- Incoming bus request
-               if next_ce_i = '1' then
+               if ce_i = '1' then
 
                        -- Mapping:
                        -- 00 & xxxxxxxx - LX Master transmitter BRAM
                        -- 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);
@@ -108,26 +198,70 @@ 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 1) = "00000000" then
+                               if address_i(8 downto 3) = "000000" then
 
-                                       if address_i(0) = '0' then
+                                       if address_i(2 downto 0) = "000" then
                                                -- LX Master reset
                                                if bls_i(0) = '1' then
                                                        reset_reg_s          <= data_i(0);
                                                        reset_reg_wr_s       <= '1';
                                                else
                                                        -- Ugh, hack :-)
-                                                       state_o_s            <= reset_reg_r;
+                                                       state_o_s(0)         <= reset_reg_r;
+                                                       state_o_s(1)         <= '0';
+                                                       state_o_s(15 downto 2) <= (others => '0');
                                                end if;
-                                       else
+                                       elsif address_i(2 downto 0) = "001" then
                                                -- LX Master register
                                                if bls_i(0) = '1' then
                                                        register_trans_in_s  <= data_i(0);
                                                        register_trans_wr_s  <= '1';
                                                else
-                                                       state_o_s            <= register_trans_out_s;
+                                                       state_o_s(1 downto 0) <= register_trans_out_s;
+                                                       state_o_s(15 downto 2) <= (others => '0');
+                                               end if;
+                                       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) = "011" then
+                                               -- LX Master period register
+                                               if bls_i(0) = '1' then
+                                                       register_cycle_in_s  <= data_i(cycle_cnt_width_c-1 downto 0);
+                                                       register_cycle_wr_s  <= '1';
+                                               else
+                                                       state_o_s            <= (15 downto cycle_cnt_width_c => '0') &
+                                                                               register_cycle_out_s;
+                                               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(1 downto 0) <= register_recv_out_s;
+                                                       state_o_s(15 downto 2) <= (others => '0');
+                                               end if;
+                                       elsif address_i(2 downto 0) = "101" then
+                                               -- LX Master receiver done divisor
+                                               if bls_i(0) = '1' then
+                                                       rx_done_ratio_s <= data_i(rx_done_div_width_c + 8 - 1 downto 8);
+                                                       rx_done_ratio_wr_s  <= '1';
+                                               else
+                                                       state_o_s(rx_done_cnt_width_c - 1 downto 0) <= 
+                                                               std_logic_vector(to_unsigned(rx_done_cnt_r, rx_done_cnt_width_c));
+                                                       state_o_s(7 downto rx_done_cnt_width_c) <= (others => '0');
+                                                       state_o_s(rx_done_div_width_c + 8 - 1 downto 8) <= rx_done_ratio_r;
+                                                       state_o_s(15 downto rx_done_div_width_c + 8) <= (others => '0');
                                                end if;
                                        end if;
 
@@ -138,16 +272,19 @@ wire_in:
        end process;
 
 wire_out:
-       process(ce_s, mem_trans_data_s, mem_trans_out_r, state_o_r)
+       process(ce_r, mem_trans_data_s, mem_trans_out_r, 
+               mem_recv_data_s, mem_recv_out_r, state_o_r)
        begin
 
                data_o <= (others => '0');
 
-               if ce_s = '1' then
+               if ce_r = '1' then
                        if mem_trans_out_r = '1' then
-                               data_o    <= mem_trans_data_s;
+                               data_o             <= mem_trans_data_s;
+                       elsif mem_recv_out_r = '1' then
+                               data_o             <= mem_recv_data_s;
                        else
-                               data_o(0) <= state_o_r;
+                               data_o             <= state_o_r;
                        end if;
                end if;
 
@@ -157,14 +294,27 @@ update:
        process
        begin
                wait until clk_i'event and clk_i= '1';
-               ce_s            <= next_ce_i;
+               ce_r            <= 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
-                       reset_reg_r <= '1';
+                       reset_reg_r   <= '1';
                elsif reset_reg_wr_s = '1' then
-                       reset_reg_r <= reset_reg_s;
+                       reset_reg_r   <= reset_reg_s;
+               end if;
+
+               if reset_i = '1' then
+                       rx_done_ratio_r <= ( 0 => '1', others => '0');
+               elsif rx_done_ratio_wr_s = '1' then
+                       rx_done_ratio_r <= rx_done_ratio_s;
+               end if;
+
+               if reset_i = '1' then
+                       rx_done_cnt_r <= 0;
+               elsif rx_done_s = '1' then
+                       rx_done_cnt_r <= rx_done_cnt_r + 1;
                end if;
 
        end process;