cpu: wait when mem_busy is high

This commit is contained in:
Paul Mathieu
2021-03-06 19:11:11 -08:00
parent 634596fd0f
commit 1e6dc25c88
2 changed files with 45 additions and 15 deletions

View File

@@ -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)