-------------------------------------------------------------------------- -- Project: JIPS, a portable 32-bit RISC CPU written in VHDL -- This file: The pipeline -- -- Copyright (C) 2008 J. Ahrensfeld -- -- This program is free software: 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 program 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 this program. If not, see . -- -- For questions and ideas, please contact the author at jens@jayfield.org -- -------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.numeric_std.ALL; library work; use work.mips_types.all; use work.mips_instr.all; entity pipeline is Port ( rst : in STD_LOGIC; clk : in STD_LOGIC; halt : in STD_LOGIC; int : in unsigned(5 downto 0); imem_rdy : in STD_LOGIC; imem_en : out STD_LOGIC; imem_addr : out word_t; imem_data : in word_t; dmem_rdy : in STD_LOGIC; dmem_en : out STD_LOGIC; dmem_re : out STD_LOGIC; dmem_we : out unsigned(3 downto 0); dmem_addr : out word_t; dmem_din : in word_t; dmem_dout : out word_t ); end pipeline; architecture Behavioral of pipeline is -------------------------------------------------------------------------- COMPONENT reg_dual is Generic ( addr_width : integer := 3; data_width : integer := 8 ); Port ( clk_w : in STD_LOGIC; en : in STD_LOGIC; we : in STD_LOGIC; wptr : in unsigned (addr_width-1 downto 0); din : in unsigned (data_width-1 downto 0); rptr_a : in unsigned (addr_width-1 downto 0); rptr_b : in unsigned (addr_width-1 downto 0); dout_a : out unsigned (data_width-1 downto 0); dout_b : out unsigned (data_width-1 downto 0) ); END COMPONENT; -------------------------------------------------------------------------- COMPONENT idecode_rom is Port ( nop : in std_logic; inst_in : in word_t; ctrl_out : out ctrl_lines_t ); END COMPONENT; -------------------------------------------------------------------------- COMPONENT shifter is Generic ( data_width : integer ); Port ( shift_ctrl : in shift_ctrl_t; din : in unsigned (data_width-1 downto 0); dout : out unsigned (data_width-1 downto 0) ); END COMPONENT; -------------------------------------------------------------------------- COMPONENT alu is Generic ( data_width : integer ); Port ( op1_in : in unsigned (data_width-1 downto 0); op2_in : in unsigned (data_width-1 downto 0); op2_shifted : in unsigned (data_width-1 downto 0); ctrl : in alu_ctrl_t; result : out unsigned (data_width-1 downto 0); flags : out alu_flags_t ); END COMPONENT; -------------------------------------------------------------------------- COMPONENT bcu is Generic ( data_width : integer ); Port ( op1_in : in unsigned (data_width-1 downto 0); op2_in : in unsigned (data_width-1 downto 0); flags : out bcu_flags_t ); END COMPONENT; -------------------------------------------------------------------------- COMPONENT cop is Port ( rst : in STD_LOGIC; clk : in STD_LOGIC; ce : in STD_LOGIC; IR_valid : in STD_LOGIC; IR : in word_t; events : in event_t; ctrl_in : in cop_ctrl_in_t; ctrl_out : out cop_ctrl_out_t; din : in word_t; dout : out word_t ); END COMPONENT; -------------------------------------------------------------------------- COMPONENT muldiv is Port ( rst : in std_logic; clk : in std_logic; hilo_we : in std_logic; din_hi : in word_t; din_lo : in word_t; mul_divn : in std_logic; start : in std_logic; s_un : in std_logic; hilo_sel : in std_logic; busy : out std_logic; dout : out word_t ); END COMPONENT; -------------------------------------------------------------------------- constant RESET_VECTOR : word_t := X"BFC00000"; signal ID_stage : ID_t; signal EX_stage : EX_t; signal MEM_stage : MEM_t; signal WB_stage : WB_t; signal clk_2, clk_1 : STD_LOGIC; signal hdu : hdu_t; signal cpu_rst : STD_LOGIC; signal reg_a : word_t; signal reg_b : word_t; signal ctrl_lines : ctrl_lines_t; signal ID_act : STD_LOGIC; signal EX_act : STD_LOGIC; signal MEM_act : STD_LOGIC; signal WB_act : STD_LOGIC; signal ID_nop : STD_LOGIC; signal EX_nop : STD_LOGIC; signal MEM_nop : STD_LOGIC; signal WB_nop : STD_LOGIC; signal IF_stall : STD_LOGIC; signal EX_stall : STD_LOGIC; signal MEM_stall : STD_LOGIC; signal WB_stall : STD_LOGIC; signal cpu_run : STD_LOGIC; signal branch_ce : STD_LOGIC; signal run_en : STD_LOGIC; signal mul_dep : STD_LOGIC; signal imem_dep : STD_LOGIC; signal dmem_dep : STD_LOGIC; signal cop_en : STD_LOGIC; signal cop_ctrl : cop_ctrl_in_t; signal cop_din : word_t; signal cop_dout : word_t; signal alu_result : word_t; signal mul_result : word_t; signal mul_busy : STD_LOGIC; signal events : event_t; signal bcu_op_a : word_t; signal bcu_op_b : word_t; signal bcu_flags : bcu_flags_t; attribute ram_style : string; attribute ram_style of reg_a: signal is "distributed"; attribute ram_style of reg_b: signal is "distributed"; signal pc : pc_t; -------------------------------------------------------------------------- begin clk_1 <= clk; clk_2 <= not clk; cpu_run <= not halt and run_en; events.Int <= int; events.illegal <= EX_stage.ctrl.exc_illegal; events.break <= EX_stage.ctrl.exc_break; events.syscall <= EX_stage.ctrl.exc_syscall; -- Stall Detection Unit --------------------------------------------------- imem_en <= run_en and (not (ID_stage.cop_stat.exc_strobe or mul_dep) or ID_stage.cop_stat.ec) and not dmem_dep; ID_nop <= cpu_rst or imem_dep; EX_nop <= cpu_rst or EX_stage.cop_stat.exc_strobe or mul_dep; MEM_nop <= cpu_rst or EX_stage.cop_stat.exc_strobe; WB_nop <= cpu_rst or EX_stage.cop_stat.exc_strobe or dmem_dep; IF_stall <= not cpu_run or mul_dep or ID_stage.cop_stat.ec or imem_dep or dmem_dep; EX_stall <= not cpu_run or dmem_dep; MEM_stall <= not cpu_run or dmem_dep; WB_stall <= not cpu_run; mul_dep <= ID_stage.ctrl.mul_access and (EX_stage.ctrl.mul_start or mul_busy); imem_dep <= not imem_rdy; dmem_dep <= not dmem_rdy and MEM_stage.ctrl.dmem_en; --------------------------------------------------------------------------- events.inst_load_err <= '1' when EX_stage.epc(1 downto 0) /= "00" else '0'; events.inst_priv_addr <= EX_stage.epc(word_t'left); cop_en <= not ID_nop; -------------------------------------------------------------------------- -- Muldiv -------------------------------------------------------------------------- inst_muldiv: muldiv PORT MAP ( rst => cpu_rst, clk => clk, hilo_we => EX_stage.ctrl.mul_hilo_we, din_hi => EX_stage.reg_a, din_lo => EX_stage.reg_b, mul_divn => EX_stage.ctrl.mul_mul_divn, start => EX_stage.ctrl.mul_start, s_un => EX_stage.ctrl.mul_s_un, hilo_sel => EX_stage.ctrl.mul_hilo_sel, busy => mul_busy, dout => mul_result ); -------------------------------------------------------------------------- -- Coprocessor -------------------------------------------------------------------------- inst_cop: cop PORT MAP ( rst => cpu_rst, clk => clk, ce => cop_en, events => events, IR_valid => ID_stage.ctrl.cop_instr_en, IR => ID_stage.IR, ctrl_in => cop_ctrl, ctrl_out => ID_stage.cop_stat, dout => cop_dout, din => cop_din ); cop_ctrl.bd_ex <= EX_stage.ctrl.branch; cop_ctrl.bd_mem <= MEM_stage.ctrl.branch; cop_ctrl.bd_wb <= WB_stage.ctrl.branch; cop_ctrl.epc_id <= ID_stage.epc; cop_ctrl.epc_ex <= EX_stage.epc; cop_ctrl.epc_mem <= MEM_stage.epc; cop_ctrl.epc_wb <= WB_stage.epc; cop_ctrl.dmem_addr <= EX_stage.va; -------------------------------------------------------------------------- -- IF stage -------------------------------------------------------------------------- imem_addr <= pc.curr; proc_stage_pc: process(pc, rst, IF_stall) begin if rst = '1' then pc.curr <= RESET_VECTOR after 2 ns; elsif IF_stall = '0' then if pc.is_branch then pc.curr <= pc.pc_branch after 2 ns; else pc.curr <= pc.nxt after 2 ns; end if; end if; end process; proc_stage_pc_branch: process(clk_1) begin if rising_edge(clk_1) then if IF_stall = '0' then pc.pc_branch <= pc.curr + ID_stage.bimm18; end if; end if; end process; proc_stage_pc_next: process(clk_1) begin if rising_edge(clk_1) then branch_ce <= '0'; if rst = '1' then pc.nxt <= RESET_VECTOR; pc.last <= RESET_VECTOR; elsif ID_stage.cop_stat.exc_strobe = '1' then pc.nxt <= ID_stage.cop_stat.exc_vec; elsif IF_stall = '0' then branch_ce <= '1'; pc.last <= pc.curr; if ID_stage.ctrl.jump = '1' then pc.nxt <= ID_stage.jimm32; elsif ID_stage.ctrl.jump_long = '1' then pc.nxt <= ID_stage.reg_a; else pc.nxt <= pc.curr + 4; end if; end if; end if; end process; proc_stage_branch: process(clk_2) begin if rising_edge(clk_2) and branch_ce = '1' then pc.is_branch <= false; if EX_stage.ctrl.branch = '1' then case EX_stage.ctrl.bc_src is when bc_eq_ne => if (EX_stage.ctrl.bc_not xor bcu_flags.eq) = '1' then pc.is_branch <= true; end if; when bc_lez_gtz => if (EX_stage.ctrl.bc_not xor (bcu_flags.z or bcu_flags.ltz)) = '1' then pc.is_branch <= true; end if; when bc_ltz_gez => if (EX_stage.ctrl.bc_not xor bcu_flags.ltz) = '1' then pc.is_branch <= true; end if; when others => null; end case; end if; end if; end process; process(rst, clk_1) variable reset_delay : unsigned (5 downto 0); begin if rst = '1' then reset_delay := (others => '1'); cpu_rst <= '1'; run_en <= '0'; elsif rising_edge(clk_1) then if reset_delay /= (5 downto 0 => '0') then reset_delay := reset_delay - 1; else cpu_rst <= '0'; end if; if reset_delay(reset_delay'left) = '0' then run_en <= '1'; end if; end if; end process; -------------------------------------------------------------------------- -- ID stage -------------------------------------------------------------------------- ID_act <= not ID_nop; ID_stage.IR <= imem_data; ID_stage.pcn <= pc.curr; ID_stage.op <= decode_op(ID_stage.IR) when ID_nop = '0' else NOP; ID_stage.jimm32 <= extract_jimm32(ID_stage.IR, ID_stage.pcn); ID_stage.bimm18 <= extract_bimm18(ID_stage.IR, ID_stage.pcn); ID_stage.shamt <= extract_shamt(ID_stage.IR); ID_stage.reg_a_rptr <= extract_rs(ID_stage.IR); ID_stage.reg_b_rptr <= extract_rt(ID_stage.IR); ID_stage.ctrl <= ctrl_lines; ID_stage.reg_write <= ID_stage.ctrl.reg_write or ID_stage.cop_stat.reg_write; ID_stage.epc <= pc.last; proc_stage_hdu: process(ID_stage, EX_stage, MEM_stage, WB_stage) variable read_a, read_b : boolean; variable raw_a_EX, raw_a_MEM, raw_a_WB : boolean; variable raw_b_EX, raw_b_MEM, raw_b_WB : boolean; variable reg_ptr_a : reg_ptr_t; variable reg_ptr_b : reg_ptr_t; begin reg_ptr_a := ID_stage.reg_a_rptr; reg_ptr_b := ID_stage.reg_b_rptr; raw_a_EX := reg_ptr_a = EX_stage.reg_wptr and EX_stage.wreg_we = '1'; raw_a_MEM := reg_ptr_a = MEM_stage.reg_wptr and MEM_stage.wreg_we = '1'; raw_a_WB := reg_ptr_a = WB_stage.reg_wptr and WB_stage.wreg_we = '1'; raw_b_EX := reg_ptr_b = EX_stage.reg_wptr and EX_stage.wreg_we = '1'; raw_b_MEM := reg_ptr_b = MEM_stage.reg_wptr and MEM_stage.wreg_we = '1'; raw_b_WB := reg_ptr_b = WB_stage.reg_wptr and WB_stage.wreg_we = '1'; hdu.alu_fwd_a_ex <= raw_a_EX after 1 ns; hdu.alu_fwd_a_mem <= raw_a_MEM after 1 ns; hdu.alu_fwd_a_wb <= raw_a_WB after 1 ns; hdu.alu_fwd_b_ex <= raw_b_EX after 1 ns; hdu.alu_fwd_b_mem <= raw_b_MEM after 1 ns; hdu.alu_fwd_b_wb <= raw_b_WB after 1 ns; end process; proc_stage_fwd_a: process(reg_a, hdu, EX_stage, MEM_stage, WB_stage) variable data : word_t; begin data := reg_a; if hdu.alu_fwd_a_ex then data := EX_stage.result; elsif hdu.alu_fwd_a_mem then data := MEM_stage.data; elsif hdu.alu_fwd_a_wb then data := WB_stage.data; end if; ID_stage.reg_a <= data after 2 ns; end process; proc_stage_fwd_b: process(reg_b, hdu, EX_stage, MEM_stage, WB_stage) variable data : word_t; begin data := reg_b; if hdu.alu_fwd_b_ex then data := EX_stage.result; elsif hdu.alu_fwd_b_mem then data := MEM_stage.data; elsif hdu.alu_fwd_b_wb then data := WB_stage.data; end if; ID_stage.reg_b <= data after 2 ns; end process; proc_imm_mux: process(ID_stage) variable data : word_t; begin data := extract_uimm16(ID_stage.IR); case ID_stage.ctrl.imm_src is when src_imm32 => data := extract_simm32(ID_stage.IR); when src_imm16 => data := extract_uimm16(ID_stage.IR); when src_imm16_high => data := ID_stage.IR(word_t'length/2-1 downto 0) & (word_t'length/2-1 downto 0 => '0'); when others => null; end case; ID_stage.imm <= data after 2 ns; end process; -------------------------------------------------------------------------- inst_idecode_rom: idecode_rom PORT MAP ( nop => ID_nop, inst_in => ID_stage.IR, ctrl_out => ctrl_lines ); inst_reg_dual: reg_dual GENERIC MAP ( addr_width => reg_ptr_t'length, data_width => word_t'length ) PORT MAP ( clk_w => clk_1, we => WB_stage.wreg_we, en => '1', wptr => WB_stage.reg_wptr, din => WB_stage.data, rptr_a => ID_stage.reg_a_rptr, rptr_b => ID_stage.reg_b_rptr, dout_a => reg_a, dout_b => reg_b ); -------------------------------------------------------------------------- -- EX stage -------------------------------------------------------------------------- EX_stage.reg_a_rptr <= extract_rs(EX_stage.IR); EX_stage.reg_b_rptr <= extract_rt(EX_stage.IR); EX_stage.result <= mul_result when EX_stage.ctrl.mul_access = '1' else alu_result; EX_act <= not (EX_nop or EX_stall); proc_stage_ID_EX_1: process(clk_1) begin if rising_edge(clk_1) then if cpu_rst = '1' then EX_stage.epc <= (others => '0'); elsif EX_stall = '0' then EX_stage.op <= ID_stage.op; if ID_nop = '0' then EX_stage.IR <= ID_stage.IR; else EX_stage.IR <= (others => '0'); end if; EX_stage.ctrl <= ID_stage.ctrl; EX_stage.reg_write <= ID_stage.reg_write; EX_stage.pcn <= ID_stage.pcn; EX_stage.epc <= ID_stage.epc; EX_stage.cop_stat <= ID_stage.cop_stat; if EX_nop = '1' then EX_stage.op <= NOP; EX_stage.IR <= (others => '0'); EX_stage.ctrl <= ctrl_lines_default; EX_stage.cop_stat.exc_strobe <= '0'; EX_stage.reg_write <= '0'; end if; end if; end if; end process; proc_stage_EX_except: process(EX_stage) begin events.data_load_err <= '0'; events.data_store_err <= '0'; events.alu_ovf <= '0'; events.alu_uvf <= '0'; if EX_stage.ctrl.alu_exc_en = '1' then if EX_stage.alu_flags.ovf = '1' then events.alu_ovf <= '1'; end if; if EX_stage.alu_flags.uvf = '1' then events.alu_uvf <= '1'; end if; end if; if EX_stage.ctrl.except_en = '1' then if EX_stage.ctrl.word2_en = '1' then if EX_stage.va(0) = '1' then events.data_load_err <= EX_stage.ctrl.dmem_en and not EX_stage.ctrl.dmem_we; events.data_store_err <= EX_stage.ctrl.dmem_en and EX_stage.ctrl.dmem_we; end if; elsif EX_stage.va(1 downto 0) /= "00" then events.data_load_err <= EX_stage.ctrl.dmem_en and not EX_stage.ctrl.dmem_we; events.data_store_err <= EX_stage.ctrl.dmem_en and EX_stage.ctrl.dmem_we; end if; end if; end process; proc_stage_DMEM_ADDR: process(clk_1) variable vaddr : word_t; begin if rising_edge(clk_1) and EX_act = '1' then vaddr := ID_stage.reg_a + extract_simm32(ID_stage.IR); EX_stage.va <= vaddr; if ID_stage.cop_stat.RE = '1' then EX_stage.pa_off <= not vaddr(1 downto 0); else EX_stage.pa_off <= vaddr(1 downto 0); end if; end if; end process; dmem_we <= store_be(EX_stage.pa_off, EX_stage.ctrl.dmem_we, EX_stage.ctrl.word2_en, EX_stage.ctrl.word4_en, EX_stage.ctrl.align_left, EX_stage.ctrl.byte_en_byp) after 1 ns; dmem_re <= not EX_stage.ctrl.dmem_we; dmem_en <= EX_stage.ctrl.dmem_en and not(ID_stage.cop_stat.exc_strobe) after 1 ns; dmem_dout <= store_shift(EX_stage.reg_b, EX_stage.pa_off, EX_stage.ctrl.shift_offset, EX_stage.ctrl.shift_byp) after 1ns; dmem_addr <= EX_stage.va; cop_din <= EX_stage.reg_b; -------------------------------------------------------------------------- proc_wptr_mux: process(EX_stage) variable opclass : opcode_t; variable reg_wptr : reg_ptr_t; begin opclass := extract_opc(EX_stage.IR); case opclass is when "000000" => reg_wptr := extract_rd(EX_stage.IR); when others => reg_wptr := extract_rt(EX_stage.IR); end case; EX_stage.wreg_we <= EX_stage.reg_write after 1 ns; if reg_wptr = "00000" then EX_stage.wreg_we <= '0' after 1 ns; end if; EX_stage.reg_wptr <= reg_wptr after 1 ns; case EX_stage.ctrl.wptr_srcsel is when wptr_src_imm => EX_stage.reg_wptr <= reg_wptr after 1 ns; when wptr_src_const => EX_stage.reg_wptr <= to_unsigned(31, reg_ptr_t'length) after 1 ns; EX_stage.wreg_we <= '1' after 1 ns; when others => null; end case; end process; -------------------------------------------------------------------------- proc_stage_fwd_reg_a: process(clk_1) begin if rising_edge(clk_1) then if EX_act = '1' then EX_stage.reg_a <= ID_stage.reg_a; bcu_op_a <= ID_stage.reg_a; end if; end if; end process; proc_stage_fwd_reg_b: process(clk_1) begin if rising_edge(clk_1) then if EX_act = '1' then EX_stage.reg_b <= ID_stage.reg_b; bcu_op_b <= ID_stage.reg_b; end if; end if; end process; alu_op1_mux: process(EX_stage) variable data : word_t; begin data := EX_stage.reg_a; -- case EX_stage.ctrl.alu.op1_src is -- -- when alu_src_reg => -- data := EX_stage.reg_a; -- -- when alu_src_muldiv => -- data := mul_result; -- -- when others => null; -- -- end case; EX_stage.alu_op1 <= data; end process; alu_op2_mux: process(clk_1) variable data : word_t; begin if rising_edge(clk_1) and EX_act = '1' then data := ID_stage.reg_b; case ID_stage.ctrl.alu.op2_src is when alu_src_reg => data := ID_stage.reg_b; when alu_src_imm => data := ID_stage.imm; when others => null; end case; EX_stage.alu_op2 <= data; end if; end process; shifter_sa_mux: process(clk_1) variable data : shamt_t; variable data_inv : shamt_t; begin if rising_edge(clk_1) and EX_act = '1' then data := ID_stage.reg_a(4 downto 0); case ID_stage.ctrl.shamt2_srcsel is when sa_src_reg => data := ID_stage.reg_a(4 downto 0); when sa_src_imm => data := ID_stage.shamt; when others => null; end case; data_inv := not data + 1; if ID_stage.ctrl.alu.shift_right = '0' then EX_stage.shift_ctrl.shamt_rnd <= data_inv after 2 ns; else EX_stage.shift_ctrl.shamt_rnd <= data after 2 ns; end if; EX_stage.shift_ctrl.shamt_nrm <= data after 1 ns; EX_stage.shift_ctrl.shift_right <= ID_stage.ctrl.alu.shift_right; EX_stage.shift_ctrl.shift_arith <= ID_stage.ctrl.alu.shift_arith; end if; end process; -------------------------------------------------------------------------- inst_shifter: shifter GENERIC MAP ( data_width => word_t'length ) PORT MAP ( shift_ctrl => EX_stage.shift_ctrl, din => EX_stage.reg_b, dout => EX_stage.alu_op2_s ); inst_alu: alu GENERIC MAP ( data_width => word_t'length ) PORT MAP ( op1_in => EX_stage.alu_op1, op2_in => EX_stage.alu_op2, op2_shifted => EX_stage.alu_op2_s, ctrl => EX_stage.ctrl.alu, result => alu_result, flags => EX_stage.alu_flags ); inst_bcu: bcu GENERIC MAP ( data_width => word_t'length ) PORT MAP ( op1_in => bcu_op_a, op2_in => bcu_op_b, flags => bcu_flags ); -------------------------------------------------------------------------- -- MEM stage -------------------------------------------------------------------------- MEM_act <= not (MEM_nop or MEM_stall); proc_stage_MEM_n: process(clk_1) begin if rising_edge(clk_1) then if MEM_stall = '0' then MEM_stage.op <= EX_stage.op; MEM_stage.wreg_we <= EX_stage.wreg_we; MEM_stage.ctrl <= EX_stage.ctrl; MEM_stage.pcn <= EX_stage.pcn; MEM_stage.epc <= EX_stage.epc; MEM_stage.pa_off <= EX_stage.pa_off; MEM_stage.reg_wptr <= EX_stage.reg_wptr; MEM_stage.cop_stat <= EX_stage.cop_stat; if EX_stage.ctrl.dmem_en = '1' then MEM_stage.ex_result <= EX_stage.reg_b; else MEM_stage.ex_result <= EX_stage.result; end if; if MEM_nop = '1' then MEM_stage.op <= NOP; MEM_stage.wreg_we <= '0'; MEM_stage.ctrl <= ctrl_lines_default; -- MEM_stage.epc <= (others => '0'); -- MEM_stage.pcn <= (others => '0'); -- MEM_stage.pa_off <= (others => '0'); -- MEM_stage.reg_wptr <= (others => '0'); -- MEM_stage.ex_result <= (others => '0'); end if; end if; end if; end process; proc_stage_MEM_mux: process(MEM_stage, dmem_din, cop_dout) variable temp1 : word_t; variable temp2 : word_t; variable data : word_t; variable be : unsigned(3 downto 0); begin data := MEM_stage.ex_result; be := load_be(MEM_stage.pa_off, MEM_stage.ctrl.align_left, MEM_stage.ctrl.byte_en_byp); if MEM_stage.cop_stat.cop_access = '1' then data := cop_dout; elsif MEM_stage.ctrl.reg_link = '1' then data := MEM_stage.pcn + 4; elsif MEM_stage.ctrl.dmem_en = '1' then temp1 := load_shift(dmem_din, MEM_stage.pa_off, MEM_stage.ctrl.shift_offset, MEM_stage.ctrl.shift_byp); temp2 := load_sign_ext(temp1, MEM_stage.ctrl.sign_ext_byp, MEM_stage.ctrl.load_signed, MEM_stage.ctrl.word2_en, MEM_stage.ctrl.word4_en); if be(0) = '1' then data(7 downto 0) := temp2(7 downto 0); end if; if be(1) = '1' then data(15 downto 8) := temp2(15 downto 8); end if; if be(2) = '1' then data(23 downto 16) := temp2(23 downto 16); end if; if be(3) = '1' then data(31 downto 24) := temp2(31 downto 24); end if; end if; MEM_stage.data <= data after 1 ns; end process; -------------------------------------------------------------------------- -- WB stage -------------------------------------------------------------------------- WB_act <= not (WB_nop or WB_stall); proc_stage_WB_p: process(clk_1) begin if rising_edge(clk_1) then if WB_stall = '0' then WB_stage.op <= MEM_stage.op; WB_stage.ctrl <= MEM_stage.ctrl; WB_stage.wreg_we <= MEM_stage.wreg_we; WB_stage.reg_wptr <= MEM_stage.reg_wptr; WB_stage.data <= MEM_stage.data; WB_stage.epc <= MEM_stage.epc; if WB_nop = '1' then WB_stage.op <= NOP; WB_stage.ctrl <= ctrl_lines_default; WB_stage.wreg_we <= '0'; -- WB_stage.epc <= (others => '0'); -- WB_stage.reg_wptr <= (others => '0'); -- WB_stage.data <= (others => '0'); end if; end if; end if; end process; -------------------------------------------------------------------------- end Behavioral;