URL
https://opencores.org/ocsvn/rv01_riscv_core/rv01_riscv_core/trunk
Subversion Repositories rv01_riscv_core
[/] [rv01_riscv_core/] [trunk/] [VHDL/] [RV01_pipe_a.vhd] - Rev 2
Go to most recent revision | 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-A (dedicated) decoder --------------------------------------------------------------- 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_IDEC_PKG.all; use WORK.RV01_OP_PKG.all; entity RV01_PIPE_A_DEC is port( INSTR_i : in DEC_INSTR_T; FWDE_o : out std_logic; SEL_o : out std_logic_vector(4-1 downto 0) ); end RV01_PIPE_A_DEC; architecture ARC of RV01_PIPE_A_DEC is begin -- Result forward-enable flag FWDE_o <= '1' when ( INSTR_i.IMNMC = IM_ADD or INSTR_i.IMNMC = IM_ADDI or INSTR_i.IMNMC = IM_SLL or INSTR_i.IMNMC = IM_SLLI or INSTR_i.IMNMC = IM_SRL or INSTR_i.IMNMC = IM_SRLI or INSTR_i.IMNMC = IM_SRA or INSTR_i.IMNMC = IM_SRAI or INSTR_i.IMNMC = IM_AND or INSTR_i.IMNMC = IM_ANDI or INSTR_i.IMNMC = IM_OR or INSTR_i.IMNMC = IM_ORI or INSTR_i.IMNMC = IM_XOR or INSTR_i.IMNMC = IM_XORI or INSTR_i.IMNMC = IM_LW ) else '0'; -- pipe-A operation selector process(INSTR_i) begin case INSTR_i.IMNMC is when IM_ADD|IM_ADDI => SEL_o <= "0001"; when IM_SLL|IM_SLLI|IM_SRL|IM_SRLI|IM_SRA|IM_SRAI => SEL_o <= "0010"; when IM_AND|IM_ANDI|IM_OR|IM_ORI|IM_XOR|IM_XORI => SEL_o <= "0100"; when others => SEL_o <= "1000"; -- lw end case; end process; end ARC; --------------------------------------------------------------- -- A-pipeline ALU --------------------------------------------------------------- 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_IDEC_PKG.all; use WORK.RV01_OP_PKG.all; entity RV01_PIPE_A_ALU is port( SEL_i : in std_logic_vector(4-1 downto 0); SU_i : in std_logic; OP_i : in ALU_OP_T; OPA_i : in SDWORD_T; OPB_i : in SDWORD_T; RES_o : out SDWORD_T -- result ); end RV01_PIPE_A_ALU; architecture ARC of RV01_PIPE_A_ALU is constant OP_ADD : natural := 0; constant OP_SHF : natural := 1; constant OP_LOG : natural := 2; constant OP_LOAD : natural := 3; component RV01_ADDER_F is generic( LEN1 : integer := 16; LEN2 : integer := 16 ); port( OPA_i : in signed(LEN1+LEN2-1 downto 0); OPB_i : in signed(LEN1+LEN2-1 downto 0); CI_i : in std_logic; SUM_o : out signed(LEN1+LEN2-1 downto 0) ); 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 ZERO : std_logic := '0'; signal ONE : std_logic := '1'; signal ADD_RES : SDWORD_T; signal LOG_RES : SDWORD_T; signal LC : LOG_CTRL; signal RES : SDWORD_T; begin ------------------------------------ -- addition ------------------------------------ -- carry-select adder (to improve timing) U_ADD : RV01_ADDER_F generic map( LEN1 => SDLEN/2, LEN2 => SDLEN/2 ) port map( OPA_i => OPA_i, OPB_i => OPB_i, CI_i => ZERO, SUM_o => ADD_RES ); ------------------------------------ -- Logic unit operation selection ------------------------------------ process(OP_i) begin case OP_i is when ALU_AND => LC <= LC_AND; when ALU_OR => LC <= LC_OR; when others => LC <= LC_XOR; end case; 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 ); -- Result mux RES <= ADD_RES when (SEL_i(OP_ADD) = '1') else LOG_RES; RES_o <= RES; end ARC; --------------------------------------------------------------- -- A-pipeline result mux (IX2 stage) --------------------------------------------------------------- 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_IDEC_PKG.all; entity RV01_PIPE_A_RMX_X2 is generic( NW : natural := 2 ); port( OPA_V_i : in std_logic; OPB_V_i : in std_logic; OPA_i : in SDWORD_T; OPB_i : in SDWORD_T; INSTR_i : in DEC_INSTR_T; IX3_V_i : in std_logic_vector(NW-1 downto 0); IX3_INSTR_i : in DEC_INSTR_VEC_T(NW-1 downto 0); IX3_RES0_i : in SDWORD_T; IX3_RES1_i : in SDWORD_T; OPA_V_o : out std_logic; OPB_V_o : out std_logic; OPA_o : out SDWORD_T; OPB_o : out SDWORD_T ); end RV01_PIPE_A_RMX_X2; architecture ARC of RV01_PIPE_A_RMX_X2 is signal SELA1,SELB1 : std_logic; signal UOPA,UOPB : SDWORD_T; signal UOPA_V,UOPB_V : std_logic; begin ------------------------------------ -- Notes ------------------------------------ -- Stage IX3 provides (up to) two results per cycle, -- requiring a mux to select the desired one. -- OPA source selection flag SELA1 <= IX3_V_i(1) when ( IX3_INSTR_i(1).WRD = '1' and IX3_INSTR_i(1).RD = INSTR_i.RS1 ) else '0'; -- Updated OPA operand source mux UOPA <= IX3_RES1_i when (SELA1 = '1') else IX3_RES0_i; -- Updated OPA operand valid flag (flag is set if there's -- a valid value for it from IX3 stage). UOPA_V <= '1' when ( ( IX3_V_i(0) = '1' and IX3_INSTR_i(0).WRD = '1' and IX3_INSTR_i(0).RD = INSTR_i.RS1 ) or ( IX3_V_i(1) = '1' and IX3_INSTR_i(1).WRD = '1' and IX3_INSTR_i(1).RD = INSTR_i.RS1 ) ) else '0'; -- OPB source selection flag SELB1 <= IX3_V_i(1) when ( IX3_INSTR_i(1).WRD = '1' and IX3_INSTR_i(1).RD = INSTR_i.RS2 ) else '0'; -- Updated OPB operand source mux UOPB <= IX3_RES1_i when (SELB1 = '1') else IX3_RES0_i; -- Updated OPB operand valid flag (flag is set if there's -- a valid value for it from IX3 stage). UOPB_V <= '1' when ( ( IX3_V_i(0) = '1' and IX3_INSTR_i(0).WRD = '1' and IX3_INSTR_i(0).RD = INSTR_i.RS2 ) or ( IX3_V_i(1) = '1' and IX3_INSTR_i(1).WRD = '1' and IX3_INSTR_i(1).RD = INSTR_i.RS2 ) ) else '0'; OPA_V_o <= OPA_V_i or UOPA_V; OPB_V_o <= OPB_V_i or UOPB_V; OPA_o <= OPA_i when (OPA_V_i = '1') else UOPA; OPB_o <= OPB_i when (OPB_V_i = '1') else UOPB; end ARC; --------------------------------------------------------------- -- A-pipeline result mux (IX1 stage) --------------------------------------------------------------- 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_IDEC_PKG.all; entity RV01_PIPE_A_RMX_X1 is generic( NW : natural := 2 ); port( OPA_V_i : in std_logic; OPB_V_i : in std_logic; OPA_i : in SDWORD_T; OPB_i : in SDWORD_T; INSTR_i : in DEC_INSTR_T; IX2_V_i : in std_logic_vector(NW-1 downto 0); IX2_INSTR_i : in DEC_INSTR_VEC_T(NW-1 downto 0); IX2_RES0_i : in SDWORD_T; IX2_RES1_i : in SDWORD_T; IX3_V_i : in std_logic_vector(NW-1 downto 0); IX3_INSTR_i : in DEC_INSTR_VEC_T(NW-1 downto 0); IX3_RES0_i : in SDWORD_T; IX3_RES1_i : in SDWORD_T; OPA_V_o : out std_logic; OPB_V_o : out std_logic; OPA_o : out SDWORD_T; OPB_o : out SDWORD_T ); end RV01_PIPE_A_RMX_X1; architecture ARC of RV01_PIPE_A_RMX_X1 is signal SELA0_X2,SELB0_X2 : std_logic; signal SELA0_X3,SELB0_X3 : std_logic; signal SELA1_X2,SELB1_X2 : std_logic; signal SELA1_X3,SELB1_X3 : std_logic; signal UOPA,UOPB : SDWORD_T; signal UOPA_V,UOPB_V : std_logic; begin ------------------------------------ -- Notes ------------------------------------ -- Stages IX2 and IX3 provide (up to) two results per -- cycle, each, requiring a mux to select the desired one. -- OPA source selection flag SELA0_X2 <= IX2_V_i(0) when ( IX2_INSTR_i(0).WRD = '1' and IX2_INSTR_i(0).RD = INSTR_i.RS1 ) else '0'; SELA1_X2 <= IX2_V_i(1) when ( IX2_INSTR_i(1).WRD = '1' and IX2_INSTR_i(1).RD = INSTR_i.RS1 ) else '0'; SELA0_X3 <= IX3_V_i(0) when ( IX3_INSTR_i(0).WRD = '1' and IX3_INSTR_i(0).RD = INSTR_i.RS1 ) else '0'; SELA1_X3 <= IX3_V_i(1) when ( IX3_INSTR_i(1).WRD = '1' and IX3_INSTR_i(1).RD = INSTR_i.RS1 ) else '0'; -- Updated OPA operand source mux process( SELA0_X2,SELA1_X2,SELA0_X3,SELA1_X3, IX2_RES0_i,IX2_RES1_i,IX3_RES0_i,IX3_RES1_i ) variable S : std_logic_vector(4-1 downto 0); begin S := SELA1_X3 & SELA0_X3 & SELA1_X2 & SELA0_X2; case S is when "0001"|"0101"|"1001"|"1101" => UOPA <= IX2_RES0_i; when "0010"|"0011"|"0110"|"0111"|"1010"|"1011"|"1110"|"1111" => UOPA <= IX2_RES1_i; when "0100" => UOPA <= IX3_RES0_i; when others => UOPA <= IX3_RES1_i; end case; end process; -- Updated OPA operand valid flag (flag is set if there's -- a valid value for it from IX2 or IX3 stage). UOPA_V <= SELA0_X2 or SELA1_X2 or SELA0_X3 or SELA1_X3; -- OPB source selection flag SELB0_X2 <= IX2_V_i(0) when ( IX2_INSTR_i(0).WRD = '1' and IX2_INSTR_i(0).RD = INSTR_i.RS2 ) else '0'; -- OPA source selection flag SELB1_X2 <= IX2_V_i(1) when ( IX2_INSTR_i(1).WRD = '1' and IX2_INSTR_i(1).RD = INSTR_i.RS2 ) else '0'; -- OPA source selection flag SELB0_X3 <= IX3_V_i(0) when ( IX3_INSTR_i(0).WRD = '1' and IX3_INSTR_i(0).RD = INSTR_i.RS2 ) else '0'; SELB1_X3 <= IX3_V_i(1) when ( IX3_INSTR_i(1).WRD = '1' and IX3_INSTR_i(1).RD = INSTR_i.RS2 ) else '0'; -- Updated OPB operand source mux process( SELB0_X2,SELB1_X2,SELB0_X3,SELB1_X3, IX2_RES0_i,IX2_RES1_i,IX3_RES0_i,IX3_RES1_i ) variable S : std_logic_vector(4-1 downto 0); begin S := SELB1_X3 & SELB0_X3 & SELB1_X2 & SELB0_X2; case S is when "0001"|"0101"|"1001"|"1101" => UOPB <= IX2_RES0_i; when "0010"|"0011"|"0110"|"0111"|"1010"|"1011"|"1110"|"1111" => UOPB <= IX2_RES1_i; when "0100" => UOPB <= IX3_RES0_i; when others => UOPB <= IX3_RES1_i; end case; end process; -- Updated OPB operand valid flag (flag is set if there's -- a valid value for it from IX2 or IX3 stages). UOPB_V <= SELB0_X2 or SELB1_X2 or SELB0_X3 or SELB1_X3; OPA_V_o <= OPA_V_i or UOPA_V; OPB_V_o <= OPB_V_i or UOPB_V; OPA_o <= OPA_i when (OPA_V_i = '1') else UOPA; OPB_o <= OPB_i when (OPB_V_i = '1') else UOPB; end ARC;
Go to most recent revision | Compare with Previous | Blame | View Log