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 : gp_register_t; begin -- register file register_ram : r2_w_ram generic map ( REG_ADDR_WIDTH, WORD_WIDTH ) port map ( sys_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 ); -- sync process for read through write registers syn: process(sys_clk, reset) begin if (reset = RESET_VALUE) then rtw_rec.rtw_reg <= (others => '0'); rtw_rec.rtw_reg1 <= '0'; rtw_rec.rtw_reg2 <= '0'; elsif rising_edge(sys_clk) then rtw_rec <= rtw_rec_nxt; end if; end process; -- async process: decides between memory and read-through-write buffer on output output: process(rtw_rec) 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; end process; -- async process: checks forward condition forward: process(instr_spl, reg_w_addr, reg_wr_data) begin rtw_rec_nxt.rtw_reg <= reg_wr_data; rtw_rec_nxt.rtw_reg1 <= '0'; rtw_rec_nxt.rtw_reg2 <= '0'; if (reg_w_addr = instr_spl.reg_src_1_addr) then rtw_rec_nxt.rtw_reg1 <= '1'; end if; if (reg_w_addr = instr_spl.reg_src_2_addr) then rtw_rec_nxt.rtw_reg2 <= '1'; end if; end process; -- async process: calculates branch prediction br_pred: process(instr_spl) 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 branch_prediction_res <= instr_spl.immediate; --both 32 bit branch_prediction_bit <= '1'; end if; end process; -- async process: sign extension sign_ext: process(instr_spl) variable instr_s : instruction_rec; begin instr_s := instr_spl; -- currently no sign extension in jump implemented if (instr_s.signext = '1' and instr_s.immediate(11) = '1') then if (instr_s.opcode = "00010" or instr_s.opcode = "00011") then instr_s.immediate(31 downto 12) <= (others => '1'); end if; if (instr_s.opcode = "11010") then instr_s.immediate(31 downto 16) <= (others => '1'); end if; end if; instr_spl <= instr_s; end process; -- async process: decodes instruction split_instr: process(instruction) variable instr_s : instruction_rec; begin instr_s.predicates := instruction(31 downto 28); instr_s.opcode := instruction(27 downto 27-OPCODE_WIDTH+1); instr_s.reg_dest_addr := (others => '0'); instr_s.reg_src1_addr := (others => '0'); instr_s.reg_src2_addr := (others => '0'); instr_s.immediate := (others => '0'); instr_s.displacement := (others => '0'); instr_s.jmptype := (others => '0'); instr_s.carry := '0'; instr_s.sreg_update := '0'; instr_s.high_low := '0'; instr_s.fill := '0'; instr_s.signext := '0'; instr_s.bp := '0'; instr_s.arith := '0'; -- special function register operations missing -- case opcode is --================================================================= if (instr_s.opcode = "00000" or instr_s.opcode = "00001" or instr_s.opcode = "00100" or instr_s.opcode = "00110" or instr_s.opcode = "01000") then -- when "00000" => --add instr_s.reg_dest_addr := instruction(22 downto 19); instr_s.reg_src1_addr := instruction(18 downto 15); instr_s.reg_src2_addr := instruction(14 downto 11); instr_s.carry := instruction(1); instr_s.sreg_update := instruction(0); end if; -- when "00001" => --sub -- instr_s.reg_dest_addr := instruction(22 downto 19); -- instr_s.reg_src1_addr := instruction(18 downto 15); -- instr_s.reg_src2_addr := instruction(14 downto 11); -- instr_s.carry := instruction(1); -- instr_s.sreg_update := instruction(0); -- when "00100" => --and -- instr_s.reg_dest_addr := instruction(22 downto 19); -- instr_s.reg_src1_addr := instruction(18 downto 15); -- instr_s.reg_src2_addr := instruction(14 downto 11); -- instr_s.carry := instruction(1); --negligible -- instr_s.sreg_update := instruction(0); -- when "00110" => --or -- instr_s.reg_dest_addr := instruction(22 downto 19); -- instr_s.reg_src1_addr := instruction(18 downto 15); -- instr_s.reg_src2_addr := instruction(14 downto 11); -- instr_s.carry := instruction(1); --negligible -- instr_s.sreg_update := instruction(0); -- when "01000" => --xor -- instr_s.reg_dest_addr := instruction(22 downto 19); -- instr_s.reg_src1_addr := instruction(18 downto 15); -- instr_s.reg_src2_addr := instruction(14 downto 11); -- instr_s.carry := instruction(1); --negligible -- instr_s.sreg_update := instruction(0); --================================================================= if (instr_s.opcode = "00010" or instr_s.opcode = "00011") then -- when "00010" => --addi instr_s.reg_dest_addr := instruction(22 downto 19); instr_s.reg_src1_addr := instruction(18 downto 15); instr_s.immediate(11 downto 0) := instruction(14 downto 3); instr_s.signext := instruction(2); instr_s.carry := instruction(1); instr_s.sreg_update := instruction(0); end if; -- when "00011" => --subi -- instr_s.reg_dest_addr := instruction(22 downto 19); -- instr_s.reg_src1_addr := instruction(18 downto 15); -- instr_s.immediate(11 downto 0) := instruction(14 downto 3); -- instr_s.signext := instruction(2); -- instr_s.carry := instruction(1); -- instr_s.sreg_update := instruction(0); --================================================================= if (instr_s.opcode = "00101" or instr_s.opcode = "00111" or instr_s.opcode = "01001") then -- when "00101" => --andx instr_s.reg_dest_addr := instruction(22 downto 19); instr_s.reg_src1_addr := instruction(22 downto 19); instr_s.immediate(15 downto 0) := instruction(18 downto 3); instr_s.high_low := instruction(2); instr_s.fill := instruction(1); instr_s.sreg_update := instruction(0); end if; -- when "00111" => --orx -- instr_s.reg_dest_addr := instruction(22 downto 19); -- instr_s.reg_src1_addr := instruction(22 downto 19); -- instr_s.immediate(15 downto 0) := instruction(18 downto 3); -- instr_s.high_low := instruction(2); -- instr_s.fill := instruction(1); -- instr_s.sreg_update := instruction(0); -- -- when "01001" => --xorx -- instr_s.reg_dest_addr := instruction(22 downto 19); -- instr_s.reg_src1_addr := instruction(22 downto 19); -- instr_s.immediate(15 downto 0) := instruction(18 downto 3); -- instr_s.high_low := instruction(2); -- instr_s.fill := instruction(1); -- instr_s.sreg_update := instruction(0); -- --================================================================= if (instr_s.opcode = "01010" or instr_s.opcode = "01011") then -- when "01010" => --shift instr_s.reg_dest_addr := instruction(22 downto 19); instr_s.reg_src1_addr := instruction(18 downto 15); instr_s.immediate(4 downto 0) := instruction(14 downto 10); instr_s.left_right := instruction(3); instr_s.arith := instruction(2); instr_s.carry := instruction(1); instr_s.sreg_update := instruction(0); end if; -- when "01011" => --stackop -- instr_s.reg_dest_addr := instruction(22 downto 19); -- instr_s.reg_src1_addr := instruction(22 downto 19); -- instr_s.immediate(1 downto 0) := instruction(18 downto 17); -- instr_s.left_right := instruction(3); -- instr_s.arith := instruction(2); -- instr_s.carry := instruction(1); -- instr_s.sreg_update := instruction(0); --================================================================= if (instr_s.opcode = "01110" or instr_s.opcode = "10000" or instr_s.opcode = "10010" or instr_s.opcode = "11010") then -- when "01110" => --ldw instr_s.reg_dest_addr := instruction(22 downto 19); instr_s.reg_src1_addr := instruction(18 downto 15); instr_s.displacement(14 downto 0) := instruction(14 downto 0); instr_s.immediate(15 downto 0) := instruction(18 downto 3); instr_s.signext := instruction(2); instr_s.high_low := instruction(1); end if; -- when "10000" => --ldh -- instr_s.reg_dest_addr := instruction(22 downto 19); -- instr_s.reg_src1_addr := instruction(18 downto 15); -- instr_s.displacement(14 downto 0) := instruction(14 downto 0); -- instr_s.immediate(15 downto 0) := instruction(18 downto 3); -- instr_s.signext := instruction(2); -- instr_s.high_low := instruction(1); -- when "10010" => --ldb -- instr_s.reg_dest_addr := instruction(22 downto 19); -- instr_s.reg_src1_addr := instruction(18 downto 15); -- instr_s.displacement(14 downto 0) := instruction(14 downto 0); -- instr_s.immediate(15 downto 0) := instruction(18 downto 3); -- instr_s.signext := instruction(2); -- instr_s.high_low := instruction(1); -- when "11010" => --ldi -- instr_s.reg_dest_addr := instruction(22 downto 19); -- instr_s.reg_src1_addr := instruction(18 downto 15); -- instr_s.displacement(14 downto 0) := instruction(14 downto 0); -- instr_s.immediate(15 downto 0) := instruction(18 downto 3); -- instr_s.signext := instruction(2); -- instr_s.high_low := instruction(1); --================================================================= if (instr_s.opcode = "01111" or instr_s.opcode = "10001" or instr_s.opcode = "10011" or instr_s.opcode = "10101") then --when "01111" => --stw instr_s.reg_src1_addr := instruction(22 downto 19); -- register value instr_s.reg_src2_addr := instruction(18 downto 15); -- mem addr instr_s.displacement(14 downto 0) := instruction(14 downto 0); end if; -- when "10001" => --sth -- instr_s.reg_src1_addr := instruction(22 downto 19); -- instr_s.reg_src2_addr := instruction(18 downto 15); -- instr_s.displacement(14 downto 0) := instruction(14 downto 0); -- when "10011" => --stb -- instr_s.reg_src1_addr := instruction(22 downto 19); -- instr_s.reg_src2_addr := instruction(18 downto 15); -- instr_s.displacement(14 downto 0) := instruction(14 downto 0); -- when "10101" => --stx -- instr_s.reg_src1_addr := instruction(22 downto 19); -- instr_s.reg_src2_addr := instruction(18 downto 15); -- instr_s.displacement(14 downto 0) := instruction(14 downto 0); --================================================================= if (instr_s.opcode = "10110" or instr_s.opcode = "10111") then -- when "10110" => --jumpop instr_s.reg_src1_addr := instruction(22 downto 19); -- register value instr_s.immediate(15 downto 0) := instruction(22 downto 7); instr_s.bp := instruction(1); instr_s.jmptype := instruction(3 downto 2); instr_s.signext := instruction(0); end if; -- when "10111" => --brreg -- instr_s.reg_src1_addr := instruction(22 downto 19); -- register value -- instr_s.immediate(15 downto 0) := instruction(22 downto 7); -- negligible -- instr_s.bp := instruction(1); -- negligible -- instr_s.jmptype := instruction(3 downto 2); -- only lsb -- instr_s.signext := instruction(0); -- negligible --================================================================= if (instr_s.opcode = "11000" or instr_s.opcode = "11001") then -- when "11000" => --cmp instr_s.reg_src1_addr := instruction(22 downto 19); instr_s.reg_src2_addr := instruction(18 downto 15); instr_s.immediate(15 downto 0) := instruction(18 downto 3); end if; -- when "11001" => --cmpi -- instr_s.reg_src1_addr := instruction(22 downto 19); -- instr_s.reg_src2_addr := instruction(18 downto 15); -- instr_s.immediate(15 downto 0) := instruction(18 downto 3); -- when others => null; -- end case; instr_spl <= instr_s; end process; end behav;