-- `Deep Thought', a softcore CPU implemented on a FPGA -- -- Copyright (C) 2010 Markus Hofstaetter -- Copyright (C) 2010 Martin Perner -- Copyright (C) 2010 Stefan Rebernig -- Copyright (C) 2010 Manfred Schwarz -- Copyright (C) 2010 Bernhard Urban -- -- 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 . library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use work.mem_pkg.all; use work.core_pkg.all; use work.common_pkg.all; architecture behav of decode_stage is signal instr_spl : instruction_rec; signal rtw_rec, rtw_rec_nxt : read_through_write_rec; signal reg1_mem_data, reg2_mem_data, reg1_rd_data, reg2_rd_data : gp_register_t; signal dec_op_inst, dec_op_inst_nxt : dec_op; begin -- register file register_ram : r2_w_ram generic map ( REG_ADDR_WIDTH, WORD_WIDTH ) port map ( clk, reg_w_addr, instr_spl.reg_src1_addr, instr_spl.reg_src2_addr, reg_we, reg_wr_data, reg1_mem_data, reg2_mem_data ); decoder_inst : decoder port map ( instruction, instr_spl ); -- sync process for read through write registers syn: process(clk, reset) begin if (reset = RESET_VALUE) then rtw_rec.rtw_reg <= (others => '0'); rtw_rec.rtw_reg1 <= '0'; rtw_rec.rtw_reg2 <= '0'; rtw_rec.immediate <= (others => '0'); rtw_rec.imm_set <= '0'; dec_op_inst.condition <= (others => '1'); dec_op_inst.op_detail <= (others => '0'); dec_op_inst.op_group <= ADDSUB_OP; dec_op_inst.brpr <= '0'; --branch_prediction_bit; dec_op_inst.src1 <= (others => '0'); dec_op_inst.src2 <= (others => '0'); dec_op_inst.saddr1 <= (others => '0'); dec_op_inst.saddr2 <= (others => '0'); dec_op_inst.daddr <= (others => '0'); dec_op_inst.displacement <= (others => '0'); dec_op_inst.prog_cnt <= (others => '0'); elsif rising_edge(clk) then rtw_rec <= rtw_rec_nxt; dec_op_inst <= dec_op_inst_nxt; end if; end process; -- type dec_op is record -- condition : condition_t; -- op_group : op_info_t; -- op_detail : op_opt_t; -- brpr : std_logic; -- -- src1 : gp_register_t; -- src2 : gp_register_t; -- -- saddr1 : gp_addr_t; -- saddr2 : gp_addr_t; -- -- daddr : gp_addr_t; -- -- end record; -- output logic incl. bypassing reg-file output_next_stage: process(dec_op_inst, reg1_rd_data, reg2_rd_data, nop) begin to_next_stage <= dec_op_inst; to_next_stage.src1 <= reg1_rd_data; to_next_stage.src2 <= reg2_rd_data; if (nop = '1') then to_next_stage.condition <= "1111"; end if; end process; -- fills output register to_next: process(instr_spl, prog_cnt) begin dec_op_inst_nxt.condition <= instr_spl.predicates; dec_op_inst_nxt.op_detail <= instr_spl.op_detail; dec_op_inst_nxt.brpr <= instr_spl.bp; --branch_prediction_bit; dec_op_inst_nxt.src1 <= (others => '0'); dec_op_inst_nxt.src2 <= (others => '0'); dec_op_inst_nxt.saddr1 <= instr_spl.reg_src1_addr; dec_op_inst_nxt.saddr2 <= instr_spl.reg_src2_addr; dec_op_inst_nxt.daddr <= instr_spl.reg_dest_addr; --(others => '0'); dec_op_inst_nxt.op_group <= instr_spl.op_group; dec_op_inst_nxt.displacement <= instr_spl.displacement; dec_op_inst_nxt.prog_cnt <= prog_cnt; end process; -- async process: decides between memory and read-through-write buffer on output output: process(rtw_rec, rtw_rec_nxt, reg1_mem_data, reg2_mem_data) begin if ((rtw_rec.rtw_reg1) = '1') then reg1_rd_data <= rtw_rec.rtw_reg; else reg1_rd_data <= reg1_mem_data; end if; if ((rtw_rec.rtw_reg2) = '1') then reg2_rd_data <= rtw_rec.rtw_reg; else reg2_rd_data <= reg2_mem_data; end if; if (rtw_rec.imm_set = '1') then reg2_rd_data <= rtw_rec.immediate; end if; end process; -- async process: checks forward condition forward: process(instr_spl, reg_w_addr, reg_wr_data, reg_we) begin rtw_rec_nxt.rtw_reg <= reg_wr_data; rtw_rec_nxt.rtw_reg1 <= '0'; rtw_rec_nxt.rtw_reg2 <= '0'; rtw_rec_nxt.immediate <= (others => '0'); rtw_rec_nxt.imm_set <= '0'; --- ???? wieso rtw_rec_nxt.reg1_addr <= instr_spl.reg_src1_addr; rtw_rec_nxt.reg2_addr <= instr_spl.reg_src2_addr; if (instr_spl.op_detail(IMM_OPT) = '1') then -- or instr_spl.op_group = LDST_OP rtw_rec_nxt.immediate <= instr_spl.immediate; rtw_rec_nxt.imm_set <= '1'; end if; if (reg_w_addr = instr_spl.reg_src1_addr) then rtw_rec_nxt.rtw_reg1 <= ('1' and reg_we); end if; if (reg_w_addr = instr_spl.reg_src2_addr) then rtw_rec_nxt.rtw_reg2 <= ('1' and reg_we); end if; end process; -- async process: calculates branch prediction br_pred: process(instr_spl, prog_cnt, reset) begin branch_prediction_res <= (others => '0'); branch_prediction_bit <= '0'; if ((instr_spl.opcode = "10110" or instr_spl.opcode = "10111") and instr_spl.bp = '1') then if instr_spl.int = '0' then branch_prediction_res <= std_logic_vector(unsigned(instr_spl.immediate) + unsigned(prog_cnt)); --both 32 bit else branch_prediction_res <= instr_spl.immediate; end if; branch_prediction_bit <= '1'; end if; if reset = RESET_VALUE then branch_prediction_bit <= '0'; end if; end process; end behav;