diff --git a/cpu/cpu.vhdl b/cpu/cpu.vhdl index 84c64cb..7b9abf3 100644 --- a/cpu/cpu.vhdl +++ b/cpu/cpu.vhdl @@ -14,7 +14,8 @@ entity cpu is mem_out: out std_logic_vector(15 downto 0); mem_addr: out std_logic_vector(15 downto 0); mem_write: out std_logic; - mem_read: out std_logic + mem_read: out std_logic; + mem_busy: in std_logic ); end entity cpu; @@ -48,18 +49,20 @@ architecture behavior of cpu is signal load_reg_next, load_reg: std_logic_vector(15 downto 0); signal load_addr_next, load_addr: std_logic_vector(15 downto 0); + signal hold_inst_next, hold_inst: std_logic_vector(15 downto 0); type regbank is array(0 to 15) of std_logic_vector(15 downto 0); signal reg_d: regbank; signal reg_q: regbank; - type cpu_state_t is (RUN, LOAD, BRANCH); + type cpu_state_t is (RUN, LOAD, BRANCH, WAIT_MEM); signal cpu_state, cpu_state_next: cpu_state_t; begin cpu_alu: alu port map(a => alu_a, b => alu_b, sel => alu_sel, flag => alu_flag, q => alu_q); load_reg_r: reg port map(clk => clk, rst => rst, d => load_reg_next, q => load_reg); load_addr_r: reg port map(clk => clk, rst => rst, d => load_addr_next, q => load_addr); + hold_inst_r: reg port map(clk => clk, rst => rst, d => hold_inst_next, q => hold_inst); allregs: for i in 0 to 15 generate @@ -77,7 +80,7 @@ begin code_addr <= reg_q(14); - process(code_data, reg_q, mem_in, alu_q, alu_flag, cpu_state, load_addr, load_reg) is + process(code_data, reg_q, mem_in, mem_busy, alu_q, alu_flag, cpu_state, load_addr, load_reg) is variable inst: std_logic_vector(15 downto 0); variable regn_0: natural; variable regn_1: natural; @@ -103,6 +106,7 @@ begin load_reg_next <= load_reg; load_addr_next <= load_addr; + hold_inst_next <= hold_inst; case cpu_state is when RUN => @@ -122,6 +126,10 @@ begin when BRANCH => inst := x"0000"; -- NOP reg_d(14) <= std_logic_vector(unsigned(reg_q(14)) + 2); + when WAIT_MEM => + cpu_state_next <= RUN; + inst := hold_inst; + reg_d(14) <= std_logic_vector(unsigned(reg_q(14)) + 2); end case; regn_0 := to_integer(unsigned(inst(11 downto 8))); @@ -131,17 +139,30 @@ begin case inst(15 downto 12) is when "0000" => -- NOP when "0001" => -- LOAD rn, [rm, imm] (imm is signed 4 bits) - mem_read <= '1'; - cpu_state_next <= LOAD; - reg_d(14) <= reg_q(14); -- halt the prefetcher + if mem_busy = '1' then + reg_d(14) <= reg_q(14); -- halt the prefetcher + hold_inst_next <= inst; + cpu_state_next <= WAIT_MEM; + else + mem_read <= '1'; + cpu_state_next <= LOAD; + reg_d(14) <= reg_q(14); -- halt the prefetcher + + load_addr_next <= std_logic_vector(signed(reg_q(regn_1)) + signed(inst(3 downto 0) & '0')); + mem_addr <= std_logic_vector(signed(reg_q(regn_1)) + signed(inst(3 downto 0) & '0')); + load_reg_next(3 downto 0) <= inst(11 downto 8); + end if; - load_addr_next <= std_logic_vector(signed(reg_q(regn_1)) + signed(inst(3 downto 0) & '0')); - mem_addr <= std_logic_vector(signed(reg_q(regn_1)) + signed(inst(3 downto 0) & '0')); - load_reg_next(3 downto 0) <= inst(11 downto 8); when "0010" => -- STORE rn, [rm, imm] - mem_write <= '1'; - mem_addr <= std_logic_vector(signed(reg_q(regn_1)) + signed(inst(3 downto 0) & '0')); - mem_out <= reg_q(regn_0); + if mem_busy = '1' then + reg_d(14) <= reg_q(14); -- halt the prefetcher + hold_inst_next <= inst; + cpu_state_next <= WAIT_MEM; + else + mem_write <= '1'; + mem_addr <= std_logic_vector(signed(reg_q(regn_1)) + signed(inst(3 downto 0) & '0')); + mem_out <= reg_q(regn_0); + end if; --- ALU stuff when "0011" => do_alu := '1'; -- ADD rd, rn, rm (rd := rn + rm) diff --git a/cpu/cpu_test.vhdl b/cpu/cpu_test.vhdl index 05ceebf..8b267c9 100644 --- a/cpu/cpu_test.vhdl +++ b/cpu/cpu_test.vhdl @@ -19,7 +19,8 @@ architecture rtl of cpu_test is mem_out: out std_logic_vector(15 downto 0); mem_addr: out std_logic_vector(15 downto 0); mem_write: out std_logic; - mem_read: out std_logic + mem_read: out std_logic; + mem_busy: in std_logic ); end component; @@ -40,14 +41,14 @@ architecture rtl of cpu_test is ); signal finished, clk, rst: std_logic := '0'; - signal mem_write, mem_read: std_logic; + signal mem_write, mem_read, mem_busy: std_logic; signal rom_data, rom_addr, mem_in, mem_out, mem_addr: std_logic_vector(15 downto 0); begin dut: cpu port map(clk => clk, rst => rst, code_data => rom_data, code_addr => rom_addr, mem_in => mem_in, mem_out => mem_out, mem_addr => mem_addr, - mem_write => mem_write, mem_read => mem_read); + mem_write => mem_write, mem_read => mem_read, mem_busy => mem_busy); -- clock process @@ -97,6 +98,14 @@ begin assert(mem_addr=x"0025") report "Fail set mem_addr to 0x25" severity error; assert(mem_out=x"002a") report "Fail set mem_out to 42" severity error; + mem_busy <= '1'; + + wait for 10 ns; + assert(rom_addr=x"0008") report "Fail hold PC @08" severity error; + assert(mem_read='0') report "Fail to wait until mem_busy is low" severity error; + + mem_busy <= '0'; + wait for 10 ns; assert(rom_addr=x"000a") report "Fail PC @08" severity error; assert(mem_write='0') report "Fail set mem_write to 0" severity error;