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;