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

Subversion Repositories rv01_riscv_core

[/] [rv01_riscv_core/] [trunk/] [VHDL/] [RV01_pipe_b.vhd] - Rev 2

Compare with Previous | Blame | View Log

 
 
-----------------------------------------------------------------
--                                                             --
-----------------------------------------------------------------
--                                                             --
-- Copyright (C) 2015 Stefano Tonello                          --
--                                                             --
-- This source file may be used and distributed without        --
-- restriction provided that this copyright statement is not   --
-- removed from the file and that any derivative work contains --
-- the original copyright notice and the associated disclaimer.--
--                                                             --
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY         --
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   --
-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   --
-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      --
-- 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.                                 --
--                                                             --
-----------------------------------------------------------------
 
---------------------------------------------------------------
-- RV01 pipeline-B
---------------------------------------------------------------
 
library IEEE;
use IEEE.std_logic_1164.all; 
use IEEE.numeric_std.all;
 
library WORK;
use WORK.RV01_CONSTS_PKG.all;
use WORK.RV01_TYPES_PKG.all;
use WORK.RV01_FUNCS_PKG.all;
use WORK.RV01_ARITH_PKG.all;
use WORK.RV01_OP_PKG.all;
 
entity RV01_PIPE_B is
  port(
    CLK_i : in std_logic;
    OP_i :  in ALU_OP_T;
    SU_i : in std_logic;
    PC0_i : in unsigned(SDLEN-1 downto 0); -- from IX1
    PC1_i : in unsigned(SDLEN-1 downto 0); -- from IX2
    OPA_i : in SDWORD_T;
    OPB_i : in SDWORD_T;
 
    RES_o : out SDWORD_T
  );
end RV01_PIPE_B;
 
architecture ARC of RV01_PIPE_B is
 
  component RV01_MULU is
    port(
      CLK_i : in std_logic;
      CTRL_i : in MUL_CTRL;
      OPA_i : in SDWORD_T;
      OPB_i : in SDWORD_T;
 
      RES_o : out SDWORD_T
    );
  end component;
 
  --component RV01_SHFTU is
  --  port(
  --    CTRL_i : in SHF_CTRL;
  --    SI_i : in SDWORD_T;
  --    SHFT_i : in unsigned(5-1 downto 0);
  --    SU_i : in std_logic;
  --
  --    SO_o : out SDWORD_T
  --  );
  --end component;
 
  --component RV01_LOGICU is
  --  port(
  --    CTRL_i : in LOG_CTRL;
  --    OPA_i : in SDWORD_T;
  --    OPB_i : in SDWORD_T;
  --
  --    RES_o : out SDWORD_T
  --  );
  --end component;
 
  signal OP_q :  ALU_OP_T;
  signal OPA_q : SDWORD_T;
  signal OPB_q : SDWORD_T;
  signal RES,MUL_RES,SHF_RES,LOG_RES,AUIPC_RES,SUB_RES,SLT_RES : SDWORD_T;
  signal SHF_RES_q,LOG_RES_q,AUIPC_RES_q,SUB_RES_q,SLT_RES_q : SDWORD_T;
  signal MC : MUL_CTRL;
  --signal SC : SHF_CTRL;
  --signal LC : LOG_CTRL;
  signal MUL_SEL,SHF_SEL,LOG_SEL : std_logic;
  signal MUL_SEL_q,SHF_SEL_q,LOG_SEL_q : std_logic;
  --signal SHFT : unsigned(5-1 downto 0);
  signal OPA_SGN,OPB_SGN,SUB_RES_SGN : std_logic;
 
begin
 
  -------------------------------------------------------
  -- Notes:
  -- This module handles multiplication, shifting and
  -- boolean instructions.
  -- Shifting and boolean instructions are executed in
  -- one cycle, while multiplication ones are executed
  -- in two cycles.
  -------------------------------------------------------
 
  ------------------------------------
  -- AUIPC adder
  ------------------------------------
 
  AUIPC_RES <= to_signed(PC0_i) + OPB_i;
 
  -- pipe register
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      AUIPC_RES_q <= AUIPC_RES;
    end if;
  end process;
 
  ------------------------------------
  -- Multiply unit operation selection
  ------------------------------------
 
  process(OP_i)
  begin
    MUL_SEL <= '1';
    case OP_i is
      when ALU_MUL =>
        MC <= MC_MUL;
      when ALU_MULH =>
        MC <= MC_MULH;
      when ALU_MULHSU =>
        MC <= MC_MULHSU;
      when ALU_MULHU =>
        MC <= MC_MULHU;
      when others =>
        MUL_SEL <= '0';
        MC <= MC_NIL;
    end case;
  end process;
 
--  ------------------------------------
--  -- Shift/normalize unit operation selection
--  ------------------------------------
--
--  process(OP_i)
--  begin
--    SHF_SEL <= '1';
--    case OP_i is
--      when ALU_SHL =>
--        SC <= SC_SHL;
--      when ALU_SHR =>
--        SC <= SC_SHR;
--      when others =>
--        SHF_SEL <= '0';
--        SC <= SC_NIL;
--    end case;
--  end process;
 
--  ------------------------------------
--  -- Logic unit operation selection
--  ------------------------------------
--
--  process(OP_i)
--  begin
--    LOG_SEL <= '1';
--    case OP_i is
--      when ALU_AND =>
--        LC <= LC_AND;
--      when ALU_OR =>
--        LC <= LC_OR;
--      when ALU_XOR =>
--        LC <= LC_XOR;
--      when others =>
--        LOG_SEL <= '0';
--        LC <= LC_NIL;
--    end case;
--  end process;
 
  ------------------------------------
  -- Multiply unit
  ------------------------------------
 
  -- Note: this is a 2-cycle unit, and therefore
  -- it doesn't need a pipe register!
 
  U_MUL : RV01_MULU
    port map(
      CLK_i => CLK_i,
      CTRL_i  => MC,
      OPA_i => OPA_i,
      OPB_i => OPB_i,
 
      RES_o => MUL_RES
    );
 
  -- pipe register
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      MUL_SEL_q <= MUL_SEL;
    end if;
  end process;
 
--  ------------------------------------
--  -- Shift
--  ------------------------------------
--
--  SHFT <= to_unsigned(OPB_i(5-1 downto 0));
--
--  U_SHF : RV01_SHFTU
--    port map(
--      CTRL_i => SC,
--      SI_i => OPA_i,
--      SHFT_i => SHFT,
--      SU_i => SU_i,
--  
--      SO_o => SHF_RES
--    );
--
--  -- pipe register
--  process(CLK_i)
--  begin
--    if(CLK_i = '1' and CLK_i'event) then
--      SHF_RES_q <= SHF_RES;
--      SHF_SEL_q <= SHF_SEL;
--    end if;
--  end process;
 
--  ------------------------------------
--  -- Logic unit
--  ------------------------------------
--
--  U_LOG : RV01_LOGICU
--    port map(
--      CTRL_i => LC,
--      OPA_i => OPA_i,
--      OPB_i => OPB_i,
--  
--      RES_o => LOG_RES
--    );
--
--  -- pipe register
--  process(CLK_i)
--  begin
--    if(CLK_i = '1' and CLK_i'event) then
--      LOG_RES_q <= LOG_RES;
--      LOG_SEL_q <= LOG_SEL;
--    end if;
--  end process;
 
  ------------------------------------
  -- Subtraction
  ------------------------------------
 
  SUB_RES <= (OPA_i - OPB_i);
 
  -- subtraction result sign (to be used
  -- by SLT* instructions)
 
  SUB_RES_SGN <= SUB_RES(SDLEN-1);
 
  -- pipe register
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      SUB_RES_q <= SUB_RES;
    end if;
  end process;
 
  ------------------------------------
  -- Set-less-than
  ------------------------------------
 
  -- operand A sign
  OPA_SGN <= OPA_i(SDLEN-1);
 
  -- operand B sign
  OPB_SGN <= OPB_i(SDLEN-1);
 
  -- signed less-than comparison
  -- msb(A) msb(B) | A < B
  -------------------------
  --    0      0   | msb(A-B)
  --    0      1   |   0
  --    1      0   |   1
  --    1      1   | msb(A-B)
 
  -- unsigned less-than comparison
  -- msb(A) msb(B) | A < B
  -------------------------
  --    0      0   | msb(A-B)
  --    0      1   |   1
  --    1      0   |   0
  --    1      1   | msb(A-B)
 
  process(SU_i,OPA_SGN,OPB_SGN,SUB_RES_SGN)
  begin
    SLT_RES <= (others => '0');
    if(SU_i = '1') then
      -- signed comparison
      if(
        (OPA_SGN = OPB_SGN)
      ) then
        SLT_RES(0) <= SUB_RES_SGN;
      else
        SLT_RES(0) <= OPA_SGN;
      end if;
    else
      -- unsigned comparison
      if(
        (OPA_SGN = OPB_SGN) 
      ) then
        SLT_RES(0) <= SUB_RES_SGN;
      else
        SLT_RES(0) <= OPB_SGN;
      end if;
    end if;
  end process;
 
  -- pipe register
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      SLT_RES_q <= SLT_RES;
    end if;
  end process;
 
  ------------------------------------
  -- output flags and result mux
  ------------------------------------
 
  -- pipe register
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      --OPA_q <= OPA_i;
      OPB_q <= OPB_i;
      OP_q <= OP_i;
    end if;
  end process;
 
  -- This encoding allows to set relative priority among the
  -- functional unit according to timing requirements.
 
  process(
    OP_q,
    MUL_SEL_q,MUL_RES,
    --SHF_SEL_q,SHF_RES_q,
    --LOG_SEL_q,LOG_RES_q,
    AUIPC_RES_q,SUB_RES_q,SLT_RES_q,
    PC1_i,OPA_q,OPB_q
  )
  begin
    if(MUL_SEL_q = '1') then
      RES <= MUL_RES;
    --elsif(SHF_SEL_q = '1') then
    --  RES <= SHF_RES_q;
    elsif(OP_q = ALU_SLT) then
      RES <= SLT_RES_q;
    elsif(OP_q = ALU_SUB) then
      RES <= SUB_RES_q;
    elsif(OP_q = ALU_AUIPC) then
      RES <= AUIPC_RES_q;
    --elsif(LOG_SEL_q = '1') then
    --  RES <= LOG_RES_q;
    elsif(OP_q = ALU_JAL) then
      RES <= to_signed(PC1_i);
    --elsif(OP_q = ALU_MOVA) then
    --  RES <= OPA_q;
    else -- ALU_MOVB
      RES <= OPB_q; -- used by lui inst.
    end if;
  end process;
 
  -- result
  RES_o <= RES;
 
end ARC;
 

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.