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

Subversion Repositories iicmb

[/] [iicmb/] [trunk/] [src/] [sequencer.vhd] - Rev 2

Compare with Previous | Blame | View Log

 
--==============================================================================
--                                                                             |
--    Project: IIC Multiple Bus Controller (IICMB)                             |
--                                                                             |
--    Module:  Command sequencer for 'iicmb_m'.                                |
--    Version:                                                                 |
--             1.0,   April 29, 2016                                           |
--                                                                             |
--    Author:  Sergey Shuvalkin, (sshuv2@opencores.org)                        |
--                                                                             |
--==============================================================================
--==============================================================================
-- Copyright (c) 2016, Sergey Shuvalkin                                        |
-- All rights reserved.                                                        |
--                                                                             |
-- Redistribution and use in source and binary forms, with or without          |
-- modification, are permitted provided that the following conditions are met: |
--                                                                             |
-- 1. Redistributions of source code must retain the above copyright notice,   |
--    this list of conditions and the following disclaimer.                    |
-- 2. Redistributions in binary form must reproduce the above copyright        |
--    notice, this list of conditions and the following disclaimer in the      |
--    documentation and/or other materials provided with the distribution.     |
--                                                                             |
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE   |
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  |
-- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE    |
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR         |
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF        |
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS    |
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN     |
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)     |
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE  |
-- POSSIBILITY OF SUCH DAMAGE.                                                 |
--==============================================================================
 
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.iicmb_pkg.all;
 
 
--==============================================================================
entity sequencer is
  generic
  (
    g_cmd       :       seq_cmd_type_array := c_empty_array   -- Sequence of commands (supported: WAIT, SET_BUS and WRITE_BYTE)
  );
  port
  (
    ------------------------------------
    clk         : in    std_logic;                            -- Clock input
    s_rst       : in    std_logic;                            -- Synchronous reset (active high)
    ------------------------------------
    ------------------------------------
    cs_start    : in    std_logic;                            -- Start executing command sequence
    cs_busy     :   out std_logic;                            -- Command sequence is being executed
    cs_status   :   out std_logic_vector(2 downto 0);         -- Execution status
    ------------------------------------
    ------------------------------------
    -- Status:
    busy        : in    std_logic;                            -- Bus busy status
    captured    : in    std_logic;                            -- Bus captured status
    bus_id      : in    std_logic_vector(3 downto 0);         -- ID of selected I2C bus
    bit_state   : in    std_logic_vector(3 downto 0);         -- State of bit level FSM
    byte_state  : in    std_logic_vector(3 downto 0);         -- State of byte level FSM
    ------------------------------------
    ------------------------------------
    -- 'Generic interface' signals:
    mcmd_wr     :   out std_logic;                            -- Byte command write (active high)
    mcmd_id     :   out std_logic_vector(2 downto 0);         -- Byte command ID
    mcmd_data   :   out std_logic_vector(7 downto 0);         -- Command data
    --
    mrsp_wr     : in    std_logic;                            -- Byte response write (active high)
    mrsp_id     : in    std_logic_vector(2 downto 0);         -- Byte response ID
    mrsp_data   : in    std_logic_vector(7 downto 0)          -- Response data
    ------------------------------------
  );
end entity sequencer;
--==============================================================================
 
--==============================================================================
architecture rtl of sequencer is
 
  type cmd_type_array is array (natural range <>) of std_logic_vector(10 downto 0);
 
  ------------------------------------------------------------------------------
  function get_cmd_seq_length(a : seq_cmd_type_array) return natural is
    variable v_ret : natural := 0;
  begin
    for i in a'range loop
      case a(i).id is
        when seq_wait       => v_ret := v_ret + 1;
        when seq_set_bus    => v_ret := v_ret + 1;
        when seq_write_byte => v_ret := v_ret + 5;
      end case;
    end loop;
    return v_ret;
  end function get_cmd_seq_length;
  ------------------------------------------------------------------------------
 
  ------------------------------------------------------------------------------
  function get_cmd_seq(a : seq_cmd_type_array) return cmd_type_array is
    variable v_ret : cmd_type_array(0 to (get_cmd_seq_length(a) - 1));
    variable j : integer;
  begin
    j := 0;
    for i in a'range loop
      case a(i).id is
        when seq_wait       =>
          v_ret(j) := mcmd_wait & a(i).data;
          j := j + 1;
        when seq_set_bus    =>
          v_ret(j) := mcmd_set_bus & a(i).data;
          j := j + 1;
        when seq_write_byte =>
          v_ret(j + 0) := mcmd_start & x"00";
          v_ret(j + 1) := mcmd_write & a(i).saddr & "0";
          v_ret(j + 2) := mcmd_write & a(i).daddr;
          v_ret(j + 3) := mcmd_write & a(i).data;
          v_ret(j + 4) := mcmd_stop  & x"00";
          j := j + 5;
      end case;
    end loop;
    return v_ret;
  end function get_cmd_seq;
  ------------------------------------------------------------------------------
 
  ------------------------------------------------------------------------------
  -- Sequence of commands to execute:
  constant cmd_seq   : cmd_type_array := get_cmd_seq(g_cmd);
  ------------------------------------------------------------------------------
 
  type state_type is (s_idle, s_active);
  signal   state     : state_type                        := s_idle;
  signal   cmd_cnt   : integer range 0 to cmd_seq'length := 0;
 
begin
 
  ------------------------------------------------------------------------------
  state_proc:
  process(clk)
  begin
    if rising_edge(clk) then
      if (s_rst = '1') then
        state     <= s_idle;
        cmd_cnt   <= 0;
        cs_busy   <= '0';
        cs_status <= mrsp_done;
        mcmd_wr   <= '0';
        mcmd_id   <= "000";
        mcmd_data <= "00000000";
      else
        -- Defaults:
        mcmd_wr   <= '0';
 
        -- FSM:
        case state is
          -------------- 's_idle' state ------------------------
          when s_idle   =>
            cs_busy   <= '0';
            if (cs_start = '1') then
              if (cmd_cnt = cmd_seq'length) then
                cs_status <= mrsp_done;
                cmd_cnt   <= 0;
              else
                state     <= s_active;
                cmd_cnt   <= cmd_cnt + 1;
                cs_busy   <= '1';
                mcmd_wr   <= '1';
                mcmd_id   <= cmd_seq(cmd_cnt)(10 downto 8);
                mcmd_data <= cmd_seq(cmd_cnt)( 7 downto 0);
              end if;
            end if;
          -------------- 's_idle' state ------------------------
 
          -------------- 's_active' state ----------------------
          when s_active =>
            cs_busy   <= '1';
            if (mrsp_wr = '1') then
              case mrsp_id is
                when mrsp_nak | mrsp_arb_lost | mrsp_error =>
                  state     <= s_idle;
                  cmd_cnt   <= 0;
                  cs_busy   <= '0';
                  cs_status <= mrsp_id;
                when others        =>
                  if (cmd_cnt = cmd_seq'length) then
                    state     <= s_idle;
                    cmd_cnt   <= 0;
                    cs_busy   <= '0';
                    cs_status <= mrsp_done;
                  else
                    cmd_cnt   <= cmd_cnt + 1;
                    mcmd_wr   <= '1';
                    mcmd_id   <= cmd_seq(cmd_cnt)(10 downto 8);
                    mcmd_data <= cmd_seq(cmd_cnt)( 7 downto 0);
                  end if;
              end case;
            end if;
          -------------- 's_active' state ----------------------
        end case;
      end if;
    end if;
  end process state_proc;
  ------------------------------------------------------------------------------
 
end architecture rtl;
--==============================================================================
 
 

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.