OpenCores
URL https://opencores.org/ocsvn/gecko4/gecko4/trunk

Subversion Repositories gecko4

[/] [gecko4/] [trunk/] [GECKO4com/] [spartan200_an/] [vhdl/] [user_fifo/] [user_fifo-behavior.vhdl] - Rev 5

Compare with Previous | Blame | View Log

--------------------------------------------------------------------------------
--            _   _            __   ____                                      --
--           / / | |          / _| |  __|                                     --
--           | |_| |  _   _  / /   | |_                                       --
--           |  _  | | | | | | |   |  _|                                      --
--           | | | | | |_| | \ \_  | |__                                      --
--           |_| |_| \_____|  \__| |____| microLab                            --
--                                                                            --
--           Bern University of Applied Sciences (BFH)                        --
--           Quellgasse 21                                                    --
--           Room HG 4.33                                                     --
--           2501 Biel/Bienne                                                 --
--           Switzerland                                                      --
--                                                                            --
--           http://www.microlab.ch                                           --
--------------------------------------------------------------------------------
--   GECKO4com
--  
--   2010/2011 Dr. Theo Kluter
--  
--   This VHDL code is free code: you can redistribute it and/or modify
--   it under the terms of the GNU General Public License as published by
--   the Free Software Foundation, either version 3 of the License, or
--   (at your option) any later version.
--  
--   This VHDL code is distributed in the hope that it will be useful,
--   but WITHOUT ANY WARRANTY; without even the implied warranty of
--   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--   GNU General Public License for more details. 
--   You should have received a copy of the GNU General Public License
--   along with these sources.  If not, see <http://www.gnu.org/licenses/>.
--
 
--memory map:
-- 0x00 -> TX-fifo write data (WO)
-- 0x01 -> TX-fifo write message size (WO)
-- 0x02 -> Nr. of bytes in TX-fifo (RO)
-- 0x03 -> Max. size in bytes of TX-fifo (RO)
-- 0x04 -> Nr. of shorts in TX-fifo (RO)
-- 0x05 -> Max. size in shorts of TX-fifo (RO)
-- 0x06 -> Nr. of words in TX-fifo (RO)
-- 0x07 -> Max. size in words of TX-fifo (RO)
-- 0x08 -> RX-fifo read data (RO)
-- 0x09 -> RX-fifo read data (RO)
-- 0x0A -> Nr. of bytes in RX-fifo (RO)
-- 0x0B -> Max. size in bytes of RX-fifo (RO)
-- 0x0C -> Nr. of shorts in RX-fifo (RO)
-- 0x0D -> Max. size in shorts of RX-fifo (RO)
-- 0x0E -> Nr. of words in RX-fifo (RO)
-- 0x0F -> Max. size in words of RX-fifo (RO)
 
ARCHITECTURE no_target_specific OF user_fifo IS
 
   COMPONENT fifo_4kb_16w_8r
      PORT ( clock      : IN  std_logic;
             reset      : IN  std_logic;
             -- push port
             push       : IN  std_logic;
             push_data  : IN  std_logic_vector( 15 DOWNTO 0 );
             push_size  : IN  std_logic;
             -- pop port
             pop        : IN  std_logic;
             pop_data   : OUT std_logic_vector(  7 DOWNTO 0 );
             pop_size   : OUT std_logic;
             -- control port
             fifo_full  : OUT std_logic;
             fifo_empty : OUT std_logic;
             byte_cnt   : OUT std_logic_vector( 12 DOWNTO 0 ) );
   END COMPONENT;
 
   COMPONENT fifo_4kb_8w_16r
      PORT ( clock      : IN  std_logic;
             reset      : IN  std_logic;
             -- push port
             push       : IN  std_logic;
             push_data  : IN  std_logic_vector(  7 DOWNTO 0 );
             push_last  : IN  std_logic;
             -- pop port
             pop        : IN  std_logic;
             pop_data   : OUT std_logic_vector( 15 DOWNTO 0 );
             pop_last   : OUT std_logic_vector(  1 DOWNTO 0 );
             -- control port
             fifo_full  : OUT std_logic;
             fifo_empty : OUT std_logic;
             byte_cnt   : OUT std_logic_vector( 12 DOWNTO 0 ) );
   END COMPONENT;
 
   TYPE STATE_TYPE IS (IDLE,SIGNAL_DONE,SIGNAL_ERROR,SIGNAL_REQUEST,
                       GET_SIZE_0,GET_SIZE_1,GET_SIZE_2,GET_SIZE_3,
                       INIT_COPY,FLUSH_TX,COPY_TX_DATA,SIGNAL_MESSAGE,
                       COPY_RX_DATA,INSERT_DUMMY,SIGNAL_AVAILABLE);
 
   SIGNAL s_tx_fifo_byte_count_value   : std_logic_vector( 12 DOWNTO 0 );
   SIGNAL s_n_bus_error_next           : std_logic;
   SIGNAL s_tx_fifo_full               : std_logic;
   SIGNAL s_tx_fifo_empty              : std_logic;
   SIGNAL s_n_bus_error_reg            : std_logic;
   SIGNAL s_burst_cnt_reg              : std_logic_vector(  9 DOWNTO 0 );
   SIGNAL s_burst_cnt_next             : std_logic_vector(  9 DOWNTO 0 );
   SIGNAL s_n_end_reg                  : std_logic;
   SIGNAL s_is_my_write_burst_reg      : std_logic;
   SIGNAL s_do_push                    : std_logic;
 
   SIGNAL s_fifo_state_reg             : STATE_TYPE;
   SIGNAL s_tx_pop                     : std_logic;
   SIGNAL s_tx_pop_size                : std_logic;
   SIGNAL s_tx_pop_data                : std_logic_vector(  7 DOWNTO 0 );
   SIGNAL s_tx_payload_cnt_reg         : std_logic_vector( 32 DOWNTO 0 );
 
   SIGNAL s_rx_fifo_byte_count_value   : std_logic_vector( 12 DOWNTO 0 );
   SIGNAL s_rx_push                    : std_logic;
   SIGNAL s_rx_fifo_full               : std_logic;
   SIGNAL s_rx_byte_cnt_reg            : std_logic_vector(  1 DOWNTO 0 );
   SIGNAL s_pop_data                   : std_logic_vector(  7 DOWNTO 0 );
   SIGNAL s_pop_last                   : std_logic;
   SIGNAL s_dummy_data_reg             : std_logic_vector(  7 DOWNTO 0 );
   SIGNAL s_rx_fifo_empty              : std_logic;
   SIGNAL s_rx_fifo_pop                : std_logic;
   SIGNAL s_rx_fifo_data               : std_logic_vector( 15 DOWNTO 0 );
   SIGNAL s_rx_fifo_last               : std_logic_vector(  1 DOWNTO 0 );
   SIGNAL s_reset                      : std_logic;
 
BEGIN
   s_reset <= reset OR NOT(n_bus_reset);
 
--------------------------------------------------------------------------------
--- Here the signalling is defined                                           ---
--------------------------------------------------------------------------------
   make_error_irq : PROCESS( clock , s_do_push , s_tx_fifo_full ,
                             s_rx_fifo_empty , s_rx_fifo_pop )
   BEGIN
      IF (clock'event AND (clock = '1')) THEN
         IF ((s_do_push = '1' AND
              s_tx_fifo_full = '1') OR
             (s_rx_fifo_empty = '1' AND
              s_rx_fifo_pop = '1') OR
             (s_fifo_state_reg = FLUSH_TX)) THEN error_irq <= '1';
                                            ELSE error_irq <= '0';
         END IF;
      END IF;
   END PROCESS make_error_irq;
 
   make_data_req_irg : PROCESS( clock , reset , s_fifo_state_reg )
   BEGIN
      IF (clock'event AND (clock = '1')) THEN
         IF (reset = '0' AND
             s_fifo_state_reg = SIGNAL_REQUEST) THEN data_request_irq <= '1';
                                                ELSE data_request_irq <= '0';
         END IF;
      END IF;
   END PROCESS make_data_req_irg;
 
   make_data_available_irq : PROCESS( clock , reset , s_fifo_state_reg )
   BEGIN
      IF (clock'event AND (clock = '1')) THEN
         IF (reset = '0' AND
             s_fifo_state_reg = SIGNAL_AVAILABLE) THEN data_available_irq <= '1';
                                                  ELSE data_available_irq <= '0';
         END IF;
      END IF;
   END PROCESS make_data_available_irq;
 
--------------------------------------------------------------------------------
--- Here the bus handling is defined                                         ---
--------------------------------------------------------------------------------
   n_start_send           <= '0' WHEN bus_address( 5 DOWNTO 4 ) = "00" AND
                                      n_start_transmission = '0' AND
                                      read_n_write = '0' AND
                                      s_n_bus_error_next = '1' ELSE '1';
   n_bus_error            <= s_n_bus_error_reg;
   n_end_transmission_out <= '0' WHEN s_n_bus_error_reg = '0' OR
                                      s_n_end_reg = '0' ELSE '1';
   make_data_valid : PROCESS( clock , reset , n_bus_reset , s_burst_cnt_reg )
   BEGIN
      IF (clock'event AND (clock = '1')) THEN
         IF (reset = '0' AND
             n_bus_reset = '1' AND
             s_burst_cnt_reg(9) = '0') THEN 
            IF (s_rx_fifo_pop = '1' AND
                s_rx_fifo_last /= "00") THEN n_data_valid_out <= "01";
                                        ELSE n_data_valid_out <= "00";
            END IF;
                                       ELSE n_data_valid_out <= "11";
         END IF;
      END IF;
   END PROCESS make_data_valid;
 
   s_n_bus_error_next <= '0' WHEN bus_address( 5 DOWNTO 4) = "00" AND
                                  n_start_transmission = '0' AND
                                  ((bus_address(3 DOWNTO 1) = "000" AND
                                    (read_n_write = '1' OR
                                     s_tx_fifo_full = '1')) OR
                                   (bus_address(3 DOWNTO 1) /= "000" AND
                                    read_n_write = '0')) ELSE '1';
   s_burst_cnt_next   <= unsigned(s_burst_cnt_reg) - 1;
 
   make_data_out : PROCESS( clock , bus_address , s_tx_fifo_byte_count_value )
   BEGIN
      IF (clock'event AND (clock = '1')) THEN
         IF (bus_address(5 DOWNTO 4) = "00") THEN
            CASE (bus_address( 3 DOWNTO 0 )) IS
               WHEN  X"2"  => data_out <= "000"&s_tx_fifo_byte_count_value;
               WHEN  X"3"  => data_out <= X"1000";
               WHEN  X"4"  => data_out <= X"0"&s_tx_fifo_byte_count_value( 12 DOWNTO 1);
               WHEN  X"5"  => data_out <= X"0800";
               WHEN  X"6"  => data_out <= X"0"&"0"&s_tx_fifo_byte_count_value( 12 DOWNTO 2);
               WHEN  X"7"  => data_out <= X"0400";
               WHEN  X"8" |
                     X"9"  => data_out <= s_rx_fifo_data;
               WHEN  X"A"  => data_out <= "000"&s_rx_fifo_byte_count_value;
               WHEN  X"B"  => data_out <= X"1000";
               WHEN  X"C"  => data_out <= X"0"&s_rx_fifo_byte_count_value( 12 DOWNTO 1 );
               WHEN  X"D"  => data_out <= X"0800";
               WHEN  X"E"  => data_out <= X"0"&"0"&s_rx_fifo_byte_count_value( 12 DOWNTO 2 );
               WHEN  X"F"  => data_out <= X"0400";
               WHEN OTHERS => data_out <= X"0000";
            END CASE;
                                             ELSE
            data_out <= X"0000";
         END IF;
      END IF;
   END PROCESS make_data_out;
 
   make_n_bus_error_reg : PROCESS( clock , s_n_bus_error_next )
   BEGIN
      IF (clock'event AND (clock = '1')) THEN
         s_n_bus_error_reg <= s_n_bus_error_next;
      END IF;
   END PROCESS make_n_bus_error_reg;
 
   make_n_end_reg : PROCESS( clock , reset , n_bus_reset , s_burst_cnt_reg ,
                             s_burst_cnt_next )
   BEGIN
      IF (clock'event AND (clock = '1')) THEN
         IF (reset = '0' AND
             n_bus_reset = '1' AND
             s_burst_cnt_reg(9) = '0' AND
             s_burst_cnt_next(9) = '1') THEN s_n_end_reg <= '0';
                                        ELSE s_n_end_reg <= '1';
         END IF;
      END IF;
   END PROCESS make_n_end_reg;
 
   make_burst_cnt_reg : PROCESS( clock , reset , n_bus_reset , s_burst_cnt_reg )
   BEGIN
      IF (clock'event AND (clock = '1')) THEN
         IF (n_bus_reset = '0' OR
             reset = '1') THEN s_burst_cnt_reg <= (OTHERS => '1');
         ELSIF (bus_address( 5 DOWNTO 4 ) = "00" AND
                n_start_transmission = '0' AND
                read_n_write = '1' AND
                s_n_bus_error_next = '1') THEN
            s_burst_cnt_reg <= "0"&burst_size;
         ELSIF (s_burst_cnt_reg(9) = '0') THEN
            s_burst_cnt_reg <= s_burst_cnt_next;
         END IF;
      END IF;
   END PROCESS make_burst_cnt_reg;
 
   make_is_my_write_burst_reg : PROCESS( clock , reset , n_bus_reset )
   BEGIN
      IF (clock'event AND (clock = '1')) THEN
         IF (reset = '1' OR
             n_bus_reset = '0' OR
             n_end_transmission_in = '0') THEN s_is_my_write_burst_reg <= '0';
         ELSIF (bus_address( 5 DOWNTO 4 ) = "00" AND
                n_start_transmission = '0' AND
                read_n_write = '0' AND
                s_n_bus_error_next = '1') THEN s_is_my_write_burst_reg <= '1';
         END IF;
      END IF;
   END PROCESS make_is_my_write_burst_reg;
 
--------------------------------------------------------------------------------
--- Here the usbtmc interface is defined                                     ---
--------------------------------------------------------------------------------
   command_done  <= '1' WHEN s_fifo_state_reg = SIGNAL_DONE OR
                             s_fifo_state_reg = SIGNAL_ERROR ELSE '0';
   command_error <= '1' WHEN s_fifo_state_reg = SIGNAL_ERROR ELSE '0';
   message_available <= '1' WHEN s_fifo_state_reg = SIGNAL_MESSAGE ELSE '0';
 
   make_state_machine : PROCESS( clock , reset , s_fifo_state_reg )
      VARIABLE v_next_state : STATE_TYPE;
   BEGIN
      CASE (s_fifo_state_reg) IS
         WHEN IDLE                        => IF (start_command = '1' AND
                                                 command_id = "0011100") THEN
                                                v_next_state := SIGNAL_REQUEST;
                                             ELSIF ((start_command = '1' AND
                                                     command_id = "0011011") OR
                                                    (transparent_mode = '1' AND
                                                     pop_empty = '0')) THEN
                                                v_next_state := SIGNAL_AVAILABLE;
                                             ELSIF (transparent_mode = '1' AND
                                                    s_tx_fifo_empty = '0') THEN
                                                v_next_state := SIGNAL_MESSAGE;
                                                                  ELSE
                                                v_next_state := IDLE;
                                             END IF;
         WHEN SIGNAL_REQUEST              |
              SIGNAL_MESSAGE              => v_next_state := GET_SIZE_0;
         WHEN GET_SIZE_0                  => IF (s_tx_fifo_empty = '0') THEN
                                                IF (s_tx_pop_size = '0') THEN
                                                   v_next_state := FLUSH_TX;
                                                                         ELSE
                                                   v_next_state := GET_SIZE_1;
                                                END IF;
                                                                        ELSE
                                                v_next_state := GET_SIZE_0;
                                             END IF;
         WHEN GET_SIZE_1                  => IF (s_tx_fifo_empty = '0') THEN
                                                v_next_state := GET_SIZE_2;
                                                                        ELSE
                                                v_next_state := GET_SIZE_1;
                                             END IF;
         WHEN GET_SIZE_2                  => IF (s_tx_fifo_empty = '0') THEN
                                                v_next_state := GET_SIZE_3;
                                                                        ELSE
                                                v_next_state := GET_SIZE_2;
                                             END IF;
         WHEN GET_SIZE_3                  => IF (s_tx_fifo_empty = '0') THEN
                                                v_next_state := INIT_COPY;
                                                                        ELSE
                                                v_next_state := GET_SIZE_3;
                                             END IF;
         WHEN INIT_COPY                   => v_next_state := COPY_TX_DATA;
         WHEN COPY_TX_DATA                => IF (s_tx_payload_cnt_reg(32) = '1') THEN
                                                v_next_state := SIGNAL_DONE;
                                                                                 ELSE
                                                v_next_state := COPY_TX_DATA;
                                             END IF;
         WHEN FLUSH_TX                    => IF (s_tx_fifo_empty = '1') THEN
                                                v_next_state := SIGNAL_ERROR;
                                                                        ELSE
                                                v_next_state := FLUSH_TX;
                                             END IF;
         WHEN SIGNAL_AVAILABLE            => v_next_state := COPY_RX_DATA;
         WHEN COPY_RX_DATA                => IF (s_rx_push = '1' AND
                                                 pop_last = '1') THEN
                                                v_next_state := INSERT_DUMMY;
                                                                 ELSE
                                                v_next_state := COPY_RX_DATA;
                                             END IF;
         WHEN INSERT_DUMMY                => IF (s_rx_byte_cnt_reg = "00") THEN
                                                v_next_state := SIGNAL_DONE;
                                                                           ELSE
                                                v_next_state := INSERT_DUMMY;
                                             END IF;
         WHEN OTHERS                      => v_next_state := IDLE;
      END CASE;
      IF (clock'event AND (clock = '1')) THEN 
         IF (reset = '1') THEN s_fifo_state_reg <= IDLE;
                          ELSE s_fifo_state_reg <= v_next_state;
         END IF;
      END IF;
   END PROCESS make_state_machine;
 
   make_tx_payload_cnt_reg : PROCESS( clock , reset , s_tx_payload_cnt_reg )
      VARIABLE v_pop_data : std_logic_vector( 7 DOWNTO 0 );
   BEGIN
      IF (clock'event AND (clock = '1')) THEN
         IF (reset = '1') THEN s_tx_payload_cnt_reg <= (OTHERS => '1');
         ELSIF (s_tx_fifo_empty = '0' AND
                (s_fifo_state_reg = GET_SIZE_0 OR
                 s_fifo_state_reg = GET_SIZE_1 OR
                 s_fifo_state_reg = GET_SIZE_2 OR
                 s_fifo_state_reg = GET_SIZE_3)) THEN
            IF (s_tx_pop = '1') THEN v_pop_data := s_tx_pop_data;
                                ELSE v_pop_data := X"00";
            END IF;
            s_tx_payload_cnt_reg(32) <= '0';
            s_tx_payload_cnt_reg(31 DOWNTO 24) <= v_pop_data;
            s_tx_payload_cnt_reg(23 DOWNTO  0) <= s_tx_payload_cnt_reg(31 DOWNTO 8 );
         ELSIF (s_tx_pop = '1' OR
                s_fifo_state_reg = INIT_COPY) THEN
            s_tx_payload_cnt_reg <= unsigned(s_tx_payload_cnt_reg) - 1;
         END IF;
      END IF;
   END PROCESS make_tx_payload_cnt_reg;
 
   make_rx_byte_cnt_reg : PROCESS( clock , reset , s_fifo_state_reg , s_rx_push)
   BEGIN
      IF (clock'event AND (clock = '1')) THEN
         IF (reset = '1' OR
             s_fifo_state_reg = IDLE) THEN s_rx_byte_cnt_reg <= "00";
         ELSIF (s_rx_push = '1') THEN
            s_rx_byte_cnt_reg <= unsigned(s_rx_byte_cnt_reg) + 1;
         END IF;
      END IF;
   END PROCESS make_rx_byte_cnt_reg;
 
--------------------------------------------------------------------------------
--- Here the tx-fifo is defined                                              ---
--------------------------------------------------------------------------------
   s_do_push     <= '1' WHEN s_is_my_write_burst_reg = '1' AND
                             n_data_valid_in = "00" ELSE '0';
   s_tx_pop      <= '1' WHEN s_tx_fifo_empty = '0' AND
                             (s_fifo_state_reg = FLUSH_TX OR
                              (s_tx_pop_size = '1' AND
                               (s_fifo_state_reg = GET_SIZE_0 OR
                                s_fifo_state_reg = GET_SIZE_1 OR
                                s_fifo_state_reg = GET_SIZE_2 OR
                                s_fifo_state_reg = GET_SIZE_3)) OR
                              (s_fifo_state_reg = COPY_TX_DATA AND
                               s_tx_payload_cnt_reg(32) = '0' AND
                               fifo_full = '0')) ELSE '0';
   s_rx_push     <= '1' WHEN (s_fifo_state_reg = COPY_RX_DATA AND
                              s_rx_fifo_full = '0' AND
                              pop_empty = '0') OR
                             (s_fifo_state_reg = INSERT_DUMMY AND
                              s_rx_byte_cnt_reg /= "00") ELSE '0';
   pop           <= '1' WHEN s_fifo_state_reg = COPY_RX_DATA AND
                             s_rx_push = '1' ELSE '0';
   s_pop_data    <= s_dummy_data_reg WHEN s_fifo_state_reg = INSERT_DUMMY ELSE pop_data;
   s_pop_last    <= '1' WHEN s_fifo_state_reg = INSERT_DUMMY ELSE pop_last;
   s_rx_fifo_pop <= '1' WHEN s_burst_cnt_reg(9) = '0' AND
                             (bus_address( 3 DOWNTO 0 ) = X"8" OR
                              bus_address( 3 DOWNTO 0 ) = X"9") ELSE '0';
 
   make_scpi_fifo_if : PROCESS( clock , reset )
   BEGIN
      IF (clock'event AND (clock = '1')) THEN
         IF (reset = '1' OR
             s_tx_pop = '0') THEN push      <= '0';
                                  push_size <= '0';
                                  push_data <= (OTHERS => '0');
                             ELSE
            IF (s_fifo_state_reg = FLUSH_TX) THEN push <= '0';
                                             ELSE push <= '1';
            END IF;
            push_size <= s_tx_pop_size;
            push_data <= s_tx_pop_data;
         END IF;
      END IF;
   END PROCESS make_scpi_fifo_if;
 
   make_dummy_data_reg : PROCESS( clock , reset , pop_data , pop_last ,
                                  s_rx_push )
   BEGIN
      IF (clock'event AND (clock = '1')) THEN
         IF (reset = '1') THEN s_dummy_data_reg <= X"00";
         ELSIF (s_rx_push = '1' AND
                pop_last = '1') THEN s_dummy_data_reg <= NOT(pop_data);
         END IF;
      END IF;
   END PROCESS make_dummy_data_reg;
 
   tx_fifo : fifo_4kb_16w_8r
             PORT MAP ( clock      => clock,
                        reset      => s_reset,
                        -- push port
                        push       => s_do_push,
                        push_data  => data_in,
                        push_size  => bus_address(0),
                        -- pop port
                        pop        => s_tx_pop,
                        pop_data   => s_tx_pop_data,
                        pop_size   => s_tx_pop_size,
                        -- control port
                        fifo_full  => s_tx_fifo_full,
                        fifo_empty => s_tx_fifo_empty,
                        byte_cnt   => s_tx_fifo_byte_count_value );
 
   rx_fifo : fifo_4kb_8w_16r
             PORT MAP ( clock      => clock,
                        reset      => s_reset,
                        -- push port
                        push       => s_rx_push,
                        push_data  => s_pop_data,
                        push_last  => s_pop_last,
                        -- pop port
                        pop        => s_rx_fifo_pop,
                        pop_data   => s_rx_fifo_data,
                        pop_last   => s_rx_fifo_last,
                        -- control port
                        fifo_full  => s_rx_fifo_full,
                        fifo_empty => s_rx_fifo_empty,
                        byte_cnt   => s_rx_fifo_byte_count_value );
 
 
END no_target_specific;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.