From 5356e3e07b4c3f16d4f2494100e2c4e937cb0e5b Mon Sep 17 00:00:00 2001 From: Stefan Date: Sun, 14 Nov 2010 15:10:43 +0100 Subject: [PATCH] =?utf8?q?fetch=20und=20decode=20kompilierbar,=20generelle?= =?utf8?q?=20tb,=20=C3=A4nderung=20in=20pkgs,=20eigene=20decoder=20entity?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- cpu/src/common_pkg.vhd | 55 +++++-- cpu/src/core_pkg.vhd | 56 +++----- cpu/src/decode_stage.vhd | 13 +- cpu/src/decode_stage_b.vhd | 283 ++----------------------------------- cpu/src/decoder.vhd | 16 +++ cpu/src/decoder_b.vhd | 268 +++++++++++++++++++++++++++++++++++ cpu/src/fetch_stage.vhd | 5 +- cpu/src/fetch_stage_b.vhd | 9 +- cpu/src/pipeline_tb.vhd | 174 +++++++++++++++++++++++ cpu/src/r2_w_ram.vhd | 2 + cpu/src/r2_w_ram_b.vhd | 4 +- cpu/src/r_w_ram_b.vhd | 4 +- 12 files changed, 560 insertions(+), 329 deletions(-) create mode 100644 cpu/src/decoder.vhd create mode 100644 cpu/src/decoder_b.vhd create mode 100644 cpu/src/pipeline_tb.vhd diff --git a/cpu/src/common_pkg.vhd b/cpu/src/common_pkg.vhd index 46434bc..c54829b 100644 --- a/cpu/src/common_pkg.vhd +++ b/cpu/src/common_pkg.vhd @@ -5,12 +5,20 @@ use IEEE.numeric_std.all; package common_pkg is + 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; + + subtype byte_t is std_logic_vector(BYTE_WIDTH-1 downto 0); + subtype hword_t is std_logic_vector(HWORD_WIDTH-1 downto 0); + subtype word_t is std_logic_vector(WORD_WIDTH-1 downto 0); + + subtype gp_register_t is word_t; + constant REG_ZERO : gp_register_t := (others => '0'); @@ -23,14 +31,10 @@ package common_pkg is constant NUM_OP_OPT_WIDTH : INTEGER := 5; constant COND_WIDTH : INTEGER := 4; - subtype byte_t is std_logic_vector(BYTE_WIDTH-1 downto 0); - subtype hword_t is std_logic_vector(HWORD_WIDTH-1 downto 0); - subtype word_t is std_logic_vector(WORD_WIDTH-1 downto 0); subtype instruction_word_t is std_logic_vector(WORD_WIDTH-1 downto 0); subtype instruction_addr_t is std_logic_vector(INSTR_ADDR_WIDTH-1 downto 0); - subtype gp_register_t is word_t; subtype gp_addr_t is unsigned(REG_ADDR_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_vector(DATA_ADDR_WIDTH-1 downto 0); @@ -53,13 +57,39 @@ package common_pkg is constant PSW_DISABLE : integer := 4; - - - type op_info_t is (ADDSUB_OP,AND_OP,OR_OP, XOR_OP,SHIFT_OP); subtype op_opt_rec is std_logic_vector(NUM_OP_OPT_WIDTH-1 downto 0); - type dec_op is + + 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; + + type dec_op is record condition : condition_t; op_group : op_info_t; op_detail : op_opt_rec; @@ -71,15 +101,18 @@ package common_pkg is saddr1 : gp_addr_t; saddr2 : gp_addr_t; - daddr : gp_addr_t + daddr : gp_addr_t; - end record dec_op; + end record; + + + function inc(value : in std_logic_vector; constant by : in integer := 1) return std_logic_vector; function log2c(constant value : in integer range 0 to integer'high) return integer; end package common_pkg; -package body common_pkg; +package body common_pkg is function inc(value : in std_logic_vector; constant by : in integer := 1) return std_logic_vector is begin diff --git a/cpu/src/core_pkg.vhd b/cpu/src/core_pkg.vhd index 57abe47..335ffb6 100644 --- a/cpu/src/core_pkg.vhd +++ b/cpu/src/core_pkg.vhd @@ -12,7 +12,7 @@ package core_pkg is -- active reset value RESET_VALUE : std_logic; -- active logic value - LOGIC_ACT : std_logic; + LOGIC_ACT : std_logic ); port( @@ -39,7 +39,7 @@ package core_pkg is -- active reset value RESET_VALUE : std_logic; -- active logic value - LOGIC_ACT : std_logic; + LOGIC_ACT : std_logic ); port( @@ -54,27 +54,36 @@ package core_pkg is 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 + reg1_rd_data : out gp_register_t; + reg2_rd_data : out gp_register_t; + branch_prediction_res : out instruction_word_t; + branch_prediction_bit : out std_logic ); end component decode_stage; + component decoder is + + port( + instruction : in instruction_word_t; + instr_spl : out instruction_rec + + ); + + end component decoder; component execute_stage is generic ( -- active reset value RESET_VALUE : std_logic; -- active logic value - LOGIC_ACT : std_logic; + LOGIC_ACT : std_logic ); port( --System inputs clk : in std_logic; - reset : in std_logic; + reset : in std_logic ); end component execute_stage; @@ -85,43 +94,16 @@ package core_pkg is -- active reset value RESET_VALUE : std_logic; -- active logic value - LOGIC_ACT : std_logic; + LOGIC_ACT : std_logic ); port( --System inputs clk : in std_logic; - reset : in std_logic; + reset : in std_logic ); 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 63caa7e..2b0cf49 100644 --- a/cpu/src/decode_stage.vhd +++ b/cpu/src/decode_stage.vhd @@ -5,13 +5,14 @@ use IEEE.numeric_std.all; use work.core_pkg.all; use work.common_pkg.all; + entity decode_stage is generic ( -- active reset value RESET_VALUE : std_logic; -- active logic value - LOGIC_ACT : std_logic; + LOGIC_ACT : std_logic ); port( @@ -26,11 +27,13 @@ entity decode_stage is 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 + reg1_rd_data : out gp_register_t; + reg2_rd_data : out gp_register_t; + branch_prediction_res : out instruction_word_t; + branch_prediction_bit : out std_logic ); end decode_stage; + + diff --git a/cpu/src/decode_stage_b.vhd b/cpu/src/decode_stage_b.vhd index 287f8e0..28c04c3 100644 --- a/cpu/src/decode_stage_b.vhd +++ b/cpu/src/decode_stage_b.vhd @@ -1,4 +1,5 @@ library IEEE; + use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; @@ -6,6 +7,8 @@ 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; @@ -23,7 +26,7 @@ begin ) port map ( - sys_clk, + clk, reg_w_addr, instr_spl.reg_src1_addr, instr_spl.reg_src2_addr, @@ -34,9 +37,15 @@ begin ); + decoder_inst : decoder + + port map ( + instruction, + instr_spl + ); -- sync process for read through write registers -syn: process(sys_clk, reset) +syn: process(clk, reset) begin @@ -44,7 +53,7 @@ begin rtw_rec.rtw_reg <= (others => '0'); rtw_rec.rtw_reg1 <= '0'; rtw_rec.rtw_reg2 <= '0'; - elsif rising_edge(sys_clk) then + elsif rising_edge(clk) then rtw_rec <= rtw_rec_nxt; end if; @@ -52,7 +61,7 @@ end process; -- async process: decides between memory and read-through-write buffer on output -output: process(rtw_rec) +output: process(rtw_rec, reg1_mem_data, reg2_mem_data) begin if (rtw_rec.rtw_reg1 = '1') then @@ -78,11 +87,11 @@ begin rtw_rec_nxt.rtw_reg1 <= '0'; rtw_rec_nxt.rtw_reg2 <= '0'; - if (reg_w_addr = instr_spl.reg_src_1_addr) then + if (reg_w_addr = instr_spl.reg_src1_addr) then rtw_rec_nxt.rtw_reg1 <= '1'; end if; - if (reg_w_addr = instr_spl.reg_src_2_addr) then + if (reg_w_addr = instr_spl.reg_src2_addr) then rtw_rec_nxt.rtw_reg2 <= '1'; end if; @@ -104,267 +113,5 @@ begin 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; diff --git a/cpu/src/decoder.vhd b/cpu/src/decoder.vhd new file mode 100644 index 0000000..41c5438 --- /dev/null +++ b/cpu/src/decoder.vhd @@ -0,0 +1,16 @@ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.core_pkg.all; +use work.common_pkg.all; + +entity decoder is + + port ( + instruction : in instruction_word_t; + instr_spl : out instruction_rec + ); + +end decoder; + diff --git a/cpu/src/decoder_b.vhd b/cpu/src/decoder_b.vhd new file mode 100644 index 0000000..1804811 --- /dev/null +++ b/cpu/src/decoder_b.vhd @@ -0,0 +1,268 @@ +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_d of decoder is + +begin + +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); + + if (instr_s.signext = '1' and instr_s.immediate(11) = '1') then + instr_s.immediate(31 downto 12) := (others => '1'); + end if; + 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); + + if (instr_s.signext = '1' and instr_s.immediate(11) = '1') then + instr_s.immediate(31 downto 16) := (others => '1'); + end if; + 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_d; + + +--=========================================================================== + + diff --git a/cpu/src/fetch_stage.vhd b/cpu/src/fetch_stage.vhd index c81e2ac..5713c02 100644 --- a/cpu/src/fetch_stage.vhd +++ b/cpu/src/fetch_stage.vhd @@ -2,7 +2,8 @@ library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; -use work.common_pkg; +use work.common_pkg.all; +use work.core_pkg.all; entity fetch_stage is @@ -10,7 +11,7 @@ entity fetch_stage is -- active reset value RESET_VALUE : std_logic; -- active logic value - LOGIC_ACT : std_logic; + LOGIC_ACT : std_logic ); port( diff --git a/cpu/src/fetch_stage_b.vhd b/cpu/src/fetch_stage_b.vhd index 2dd8e92..e774901 100644 --- a/cpu/src/fetch_stage_b.vhd +++ b/cpu/src/fetch_stage_b.vhd @@ -4,6 +4,7 @@ use IEEE.numeric_std.all; use work.core_pkg.all; use work.common_pkg.all; +use work.mem_pkg.all; architecture behav of fetch_stage is @@ -23,7 +24,7 @@ begin ) port map ( - sys_clk, + clk, instr_w_addr(PHYS_INSTR_ADDR_WIDTH-1 downto 0), instr_r_addr_nxt(PHYS_INSTR_ADDR_WIDTH-1 downto 0), instr_we, @@ -31,20 +32,20 @@ begin instr_rd_data ); -syn: process(sys_clk, reset) +syn: process(clk, reset) begin if (reset = RESET_VALUE) then instr_r_addr <= (others => '0'); - elsif rising_edge(sys_clk) then + elsif rising_edge(clk) then instr_r_addr <= instr_r_addr_nxt; end if; end process; -asyn: process(instr_r_addr, jump_result, prediction_result, branch_prediction_bit, alu_jump_bit) +asyn: process(instr_r_addr, jump_result, prediction_result, branch_prediction_bit, alu_jump_bit, instr_rd_data) begin diff --git a/cpu/src/pipeline_tb.vhd b/cpu/src/pipeline_tb.vhd new file mode 100644 index 0000000..43c0c98 --- /dev/null +++ b/cpu/src/pipeline_tb.vhd @@ -0,0 +1,174 @@ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.common_pkg.all; +use work.core_pkg.all; + +------------------------------------------------------------------------------- +-- ENTITY +------------------------------------------------------------------------------- +entity pipeline_tb is + +end pipeline_tb; + + +------------------------------------------------------------------------------- +-- ARCHITECTURE +------------------------------------------------------------------------------- +architecture behavior of pipeline_tb is + + constant cc : time := 30 ns; -- test clock period + + signal sys_clk_pin : std_logic; + signal sys_res_n_pin : std_logic; + --Data input + + signal dummy : std_logic; + + signal jump_result_pin : instruction_addr_t; + signal prediction_result_pin : instruction_addr_t; + signal branch_prediction_bit_pin : std_logic; + signal alu_jump_bit_pin : std_logic; + signal instruction_pin : instruction_word_t; + + signal reg_w_addr_pin : std_logic_vector(REG_ADDR_WIDTH-1 downto 0); + signal reg_wr_data_pin : gp_register_t; + signal reg_we_pin : std_logic; + signal reg1_rd_data_pin : gp_register_t; + signal reg2_rd_data_pin : gp_register_t; + + +begin + +-- instruction_ram : r_w_ram +-- generic map ( +-- PHYS_INSTR_ADDR_WIDTH, +-- WORD_WIDTH +-- ) +-- +-- port map ( +-- sys_clk, +-- instr_w_addr(PHYS_INSTR_ADDR_WIDTH-1 downto 0), +-- instr_r_addr_nxt(PHYS_INSTR_ADDR_WIDTH-1 downto 0), +-- instr_we, +-- instr_wr_data, +-- instr_rd_data +-- ); + + fetch_st : fetch_stage + generic map ( + + '0', + '1' + ) + + port map ( + --System inputs + clk => sys_clk_pin, --: in std_logic; + reset => sys_res_n_pin, --: in std_logic; + + --Data inputs + jump_result => jump_result_pin, --: in instruction_addr_t; + prediction_result => prediction_result_pin, --: in instruction_addr_t; + branch_prediction_bit => branch_prediction_bit_pin, --: in std_logic; + alu_jump_bit => alu_jump_bit_pin, --: in std_logic; + + --Data outputs + instruction => instruction_pin --: out instruction_word_t + ); + + decode_st : decode_stage + generic map ( + -- active reset value + '0', + -- active logic value + '1' + + ) + port map ( + --System inputs + clk => sys_clk_pin, --: in std_logic; + reset => sys_res_n_pin, -- : in std_logic; + + --Data inputs + instruction => instruction_pin, --: in instruction_word_t; + reg_w_addr => reg_w_addr_pin, --: in std_logic_vector(REG_ADDR_WIDTH-1 downto 0); + reg_wr_data => reg_wr_data_pin, --: in gp_register_t; + reg_we => reg_we_pin, --: in std_logic; + + --Data outputs + reg1_rd_data => reg1_rd_data_pin, --: gp_register_t; + reg2_rd_data => reg2_rd_data_pin, --: gp_register_t; + branch_prediction_res => prediction_result_pin, --: instruction_word_t; + branch_prediction_bit => branch_prediction_bit_pin --: std_logic + + ); + + + +------------------------------------------------------------------------------- +-- generate simulation clock +------------------------------------------------------------------------------- + CLKGEN : process + begin + sys_clk_pin <= '1'; + wait for cc/2; + sys_clk_pin <= '0'; + wait for cc/2; + end process CLKGEN; + +------------------------------------------------------------------------------- +-- test the design +------------------------------------------------------------------------------- + TEST_IT : process + + -- wait for n clock cycles + procedure icwait(cycles : natural) is + begin + for i in 1 to cycles loop + wait until sys_clk_pin = '1' and sys_clk_pin'event; + end loop; + end; + + begin + ----------------------------------------------------------------------------- + -- initial reset + ----------------------------------------------------------------------------- + sys_res_n_pin <= '0'; + reg_w_addr_pin <= (others => '0'); + reg_wr_data_pin <= (others => '0'); + reg_we_pin <= '0'; + + icwait(10); + dummy <= '1'; + sys_res_n_pin <= '1'; + wait until sys_res_n_pin = '1'; + + + icwait(100000); + + --------------------------------------------------------------------------- + -- exit testbench + --------------------------------------------------------------------------- + assert false + report "Test finished" + severity error; + + end process test_it; + +end behavior; + + +------------------------------------------------------------------------------- +-- configuration +------------------------------------------------------------------------------- +configuration pipeline_conf_beh of pipeline_tb is + for behavior + for fetch_st : fetch_stage use entity work.fetch_stage(behav); + end for; + for decode_st : decode_stage use entity work.decode_stage(behav); + end for; + + end for; +end pipeline_conf_beh; diff --git a/cpu/src/r2_w_ram.vhd b/cpu/src/r2_w_ram.vhd index ec15c61..23f1dda 100644 --- a/cpu/src/r2_w_ram.vhd +++ b/cpu/src/r2_w_ram.vhd @@ -2,6 +2,8 @@ library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; +use work.mem_pkg.all; + entity r2_w_ram is generic ( ADDR_WIDTH : integer range 1 to integer'high; diff --git a/cpu/src/r2_w_ram_b.vhd b/cpu/src/r2_w_ram_b.vhd index 4350511..84a3a94 100644 --- a/cpu/src/r2_w_ram_b.vhd +++ b/cpu/src/r2_w_ram_b.vhd @@ -3,12 +3,14 @@ library ieee; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; +use work.mem_pkg.all; + architecture behaviour of r2_w_ram is subtype RAM_ENTRY_TYPE is std_logic_vector(DATA_WIDTH -1 downto 0); type RAM_TYPE is array (0 to (2**ADDR_WIDTH)-1) of RAM_ENTRY_TYPE; - signal ram : RAM_TYPE; --:= (others=> x"00"); + signal ram : RAM_TYPE := (others=> x"00000001"); begin process(clk) diff --git a/cpu/src/r_w_ram_b.vhd b/cpu/src/r_w_ram_b.vhd index 50c7660..9e530fa 100644 --- a/cpu/src/r_w_ram_b.vhd +++ b/cpu/src/r_w_ram_b.vhd @@ -3,12 +3,14 @@ library ieee; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; +use work.mem_pkg.all; + architecture behaviour of r_w_ram is subtype RAM_ENTRY_TYPE is std_logic_vector(DATA_WIDTH -1 downto 0); type RAM_TYPE is array (0 to (2**ADDR_WIDTH)-1) of RAM_ENTRY_TYPE; - signal ram : RAM_TYPE; --:= (others=> x"00"); + signal ram : RAM_TYPE := ((others => b"11100000000000001001000000000000")); begin process(clk) -- 2.25.1