123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- library ieee;
- use ieee.std_logic_1164.all;
- use ieee.numeric_std.all;
- use work.core_pkg.all;
- use work.op_pkg.all;
- entity exec is
- port (
- clk : in std_logic;
- res_n : in std_logic;
- stall : in std_logic;
- flush : in std_logic;
- -- from DEC
- op : in exec_op_type;
- pc_in : in pc_type;
- -- to MEM
- pc_old_out : out pc_type;
- pc_new_out : out pc_type;
- aluresult : out data_type;
- wrdata : out data_type;
- zero : out std_logic;
- memop_in : in mem_op_type;
- memop_out : out mem_op_type;
- wbop_in : in wb_op_type;
- wbop_out : out wb_op_type;
- -- FWD
- exec_op : out exec_op_type;
- reg_write_mem : in reg_write_type;
- reg_write_wr : in reg_write_type
- );
- end entity;
- architecture rtl of exec is
- type alu_t is record
- op : alu_op_type;
- A : data_type;
- B : data_type;
- end record;
- constant INITIAL_ALU : alu_t := (
- op => ALU_NOP,
- A => (others => '0'),
- B => (others => '0')
- );
- type internal_t is record
- op : exec_op_type;
- pc : pc_type;
- memop : mem_op_type;
- wbop : wb_op_type;
- end record;
- constant INITIAL_INTERNAL : internal_t := (
- pc => (others => '0'),
- op => EXEC_NOP,
- memop => MEM_NOP,
- wbop => WB_NOP
- );
- signal internal : internal_t;
- signal int_alu : alu_t;
- signal pc_a, pc_b : pc_type;
- signal do_fwd_A, do_fwd_B : std_logic;
- signal fwd_val_A, fwd_val_B : data_type;
- signal rs1_data, rs2_data : data_type;
- begin
- -- structural
- alu_inst : entity work.alu
- port map (
- op => int_alu.op,
- A => int_alu.A,
- B => int_alu.B,
- R => aluresult,
- Z => zero
- );
-
- -- sequential
- sync : process(clk, res_n, flush, stall)
- begin
- if res_n = '0' then
- internal <= INITIAL_INTERNAL;
- elsif stall = '0' and rising_edge(clk) then
- internal.pc <= pc_in;
- internal.op <= op;
- internal.memop <= memop_in;
- internal.wbop <= wbop_in;
- end if;
- end process;
-
- -- FWD
- fwd_A_inst : entity work.fwd
- port map (
- reg_write_mem => reg_write_mem,
- reg_write_wb => reg_write_wr,
-
- reg => internal.op.rs1,
- val => fwd_val_A,
- do_fwd => do_fwd_A
- );
-
- fwd_B_inst : entity work.fwd
- port map (
- reg_write_mem => reg_write_mem,
- reg_write_wb => reg_write_wr,
-
- reg => internal.op.rs2,
- val => fwd_val_B,
- do_fwd => do_fwd_B
- );
-
- -- concurrent
- rs1_data <= fwd_val_A when do_fwd_A = '1' else internal.op.readdata1;
- rs2_data <= fwd_val_B when do_fwd_B = '1' else internal.op.readdata2;
-
- int_alu.op <= internal.op.aluop;
- int_alu.A <= x"0000" & internal.pc when internal.op.alusrc1 /= '0' else rs1_data;
- int_alu.B <= internal.op.imm when internal.op.alusrc2 /= '0' else rs2_data;
-
- pc_old_out <= internal.pc;
- pc_a <= internal.op.readdata1(15 downto 0) when (internal.op.alusrc1 and internal.op.alusrc2 and internal.op.alusrc3) = '1' else internal.pc; --case for JALR
- pc_b <= internal.op.imm(pc_type'RANGE) when internal.op.alusrc3 = '1' else (others => '0');
- pc_new_out <= std_logic_vector(signed(pc_a) + signed(pc_b));
-
- wrdata <= rs2_data;
- memop_out <= internal.memop when flush = '0' else MEM_NOP;
- wbop_out <= internal.wbop when flush = '0' else WB_NOP;
-
- exec_op <= internal.op;
- end architecture;
|