- Cleaned up
git-svn-id: http://moon:8086/svn/vhdl/trunk@82 cc03376c-175c-47c8-b038-4cd826a8556b
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user