- Cleaned up

git-svn-id: http://moon:8086/svn/vhdl/trunk@82 cc03376c-175c-47c8-b038-4cd826a8556b
This commit is contained in:
2008-10-19 21:29:45 +00:00
parent 9e404bfb06
commit 32cbb4fc13
3 changed files with 0 additions and 2224 deletions
File diff suppressed because it is too large Load Diff
-886
View File
@@ -1,886 +0,0 @@
--------------------------------------------------------------------------
-- 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 <http://www.gnu.org/licenses/>.
--
-- 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;
-19
View File
@@ -1,19 +0,0 @@
library IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
configuration cpu_irom of cpu_embedded is
for rtl
for inst_irom : irom
use entity work.irom(loadable);
end for;
end for;
end configuration cpu_irom;
configuration system_xrom of systest is
for behavior
for inst_xrom : xrom
use entity work.xrom(loadable);
end for;
end for;
end configuration system_xrom;