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;