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)

View File

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