From ae59c2addc2158d2872076fb14b5896619eaf8d6 Mon Sep 17 00:00:00 2001 From: Stefan Date: Sat, 13 Nov 2010 12:54:32 +0100 Subject: [PATCH] decode stage die erste --- cpu/src/common_pkg.vhd | 11 +- cpu/src/core_pkg.vhd | 40 +++++ cpu/src/decode_stage.vhd | 16 ++ cpu/src/decode_stage_b.vhd | 348 ++++++++++++++++++++++++++++++++++++- 4 files changed, 410 insertions(+), 5 deletions(-) diff --git a/cpu/src/common_pkg.vhd b/cpu/src/common_pkg.vhd index 0bd0be7..01548e4 100644 --- a/cpu/src/common_pkg.vhd +++ b/cpu/src/common_pkg.vhd @@ -5,8 +5,11 @@ use IEEE.numeric_std.all; package common_pkg is - constant WORD_WIDTH : INTEGER := 32; - constant BYTE_WIDTH : INTEGER := 8; + constant WORD_WIDTH : INTEGER := 32; + constant HWORD_WIDTH : INTEGER := 16; + constant BYTE_WIDTH : INTEGER := 8; + constant OPCODE_WIDTH : INTEGER := 5; + constant DISPL_WIDTH : INTEGER := 15; constant INSTR_ADDR_WIDTH : INTEGER := 32; constant PHYS_INSTR_ADDR_WIDTH : INTEGER := 11; @@ -20,6 +23,8 @@ package common_pkg is subtype gp_register_t is std_logic_vector(WORD_WIDTH-1 downto 0); subtype data_ram_word_t is std_logic_vector(WORD_WIDTH-1 downto 0); - subtype data_ram_addr_t is std_logic_vecotr(DATA_ADDR_WIDTH-1 downto 0); + subtype data_ram_addr_t is std_logic_vector(DATA_ADDR_WIDTH-1 downto 0); + + subtype opcode_t is std_logic_vector(OPCODE_WIDTH-1 downto 0); end package common_pkg; diff --git a/cpu/src/core_pkg.vhd b/cpu/src/core_pkg.vhd index 301a517..57abe47 100644 --- a/cpu/src/core_pkg.vhd +++ b/cpu/src/core_pkg.vhd @@ -46,6 +46,18 @@ package core_pkg is --System inputs clk : in std_logic; reset : in std_logic; + + --Data inputs + instruction : in instruction_word_t; + reg_w_addr : in std_logic_vector(REG_ADDR_WIDTH-1 downto 0); + reg_wr_data : in gp_register_t; + reg_we : in std_logic; + + --Data outputs + reg1_rd_data : gp_register_t; + reg2_rd_data : gp_register_t; + branch_prediction_res : instruction_word_t; + branch_prediction_bit : std_logic ); end component decode_stage; @@ -84,4 +96,32 @@ package core_pkg is end component writeback_stage; + type instruction_rec is record + + predicates : std_logic_vector(3 downto 0); + + opcode : opcode_t; + + reg_dest_addr : std_logic_vector(REG_ADDR_WIDTH-1 downto 0); + reg_src1_addr : std_logic_vector(REG_ADDR_WIDTH-1 downto 0); + reg_src2_addr : std_logic_vector(REG_ADDR_WIDTH-1 downto 0); + + immediate : std_logic_vector(WORD_WIDTH-1 downto 0); + displacement : std_logic_vector(DISPL_WIDTH-1 downto 0); + + jmptype : std_logic_vector(1 downto 0); + + carry, sreg_update, high_low, fill, signext, bp, arith, left_right : std_logic; + + end record; + + + type read_through_write_rec is record + + rtw_reg : gp_register_t; + rtw_reg1 : std_logic; + rtw_reg2 : std_logic; + + end record; + end package core_pkg; diff --git a/cpu/src/decode_stage.vhd b/cpu/src/decode_stage.vhd index 4be1c3e..63caa7e 100644 --- a/cpu/src/decode_stage.vhd +++ b/cpu/src/decode_stage.vhd @@ -2,6 +2,9 @@ library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; +use work.core_pkg.all; +use work.common_pkg.all; + entity decode_stage is generic ( @@ -15,6 +18,19 @@ entity decode_stage is --System inputs clk : in std_logic; reset : in std_logic; + + --Data inputs + instruction : in instruction_word_t; + reg_w_addr : in std_logic_vector(REG_ADDR_WIDTH-1 downto 0); + reg_wr_data : in gp_register_t; + reg_we : in std_logic; + + --Data outputs + reg1_rd_data : gp_register_t; + reg2_rd_data : gp_register_t; + branch_prediction_res : instruction_word_t; + branch_prediction_bit : std_logic + ); end decode_stage; diff --git a/cpu/src/decode_stage_b.vhd b/cpu/src/decode_stage_b.vhd index 48761ea..287f8e0 100644 --- a/cpu/src/decode_stage_b.vhd +++ b/cpu/src/decode_stage_b.vhd @@ -2,25 +2,369 @@ 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; -- 2.25.1