The ZPU (Zealot and ZPU4) fail to execute code from slow memory types. Using 1-cycle BRAM works fine, but using external SRAM which needs to delay write operations by asserting the memory busy signal fails. Note that executing from BRAM and writing to SRAM usually works fine, because often there is enough time between write accesses to the SRAM for it to finish the last operation anyway.
We fixed the problem by adding a wait state after single-cycle instructions that delays execution until the busy signal is deasserted. Hopefully I'll get a chance to attach the patches after hitting submit ;)
--- zpu_medium.vhdl 2009-09-07 14:52:13.000000000 +0000 +++ zpu_medium-fixed.vhdl 2009-09-07 14:51:50.000000000 +0000 @@ -167,12 +169,13 @@ signal read_en_r : std_logic; signal addr_r : unsigned(ADDR_W-1 downto BYTE_BITS):=(others => '0'); signal fetched_w_r : unsigned(WORD_SIZE-1 downto 0);
type state_t is(st_load2, st_popped, st_load_sp2, st_load_sp3, st_add_sp2,
st_fetch, st_execute, st_decode, st_decode2, st_resync,
st_store_sp2, st_resync2, st_resync3, st_loadb2, st_storeb2,
st_mult2, st_mult3, st_mult5, st_mult4, st_binary_op_res2,
st_binary_op_res, st_idle);
st_binary_op_res, st_idle, st_interrupt, st_wait);
signal state : state_t:=st_resync;
-- Go to st_fetch state or just do its work
@@ -517,6 +551,7 @@
FlushB(write_en_r,addr_r,inc_sp,data_o,b_r);
a_r <= unsigned(resize(signed(ex_opcode(6 downto 0)),WORD_SIZE));
Push(sp_r,a_r,b_r); state <= st_wait;
end if;
end if;
when dec_store_sp =>
@@ -582,6 +617,7 @@
a_r <= (others => '0');
a_r(ADDR_W-1 downto BYTE_BITS) <= sp_r;
Push(sp_r,a_r,b_r); state <= st_wait;
end if;
when dec_pop_pc =>
-- PC=Pop() (return)
@@ -696,6 +732,7 @@
-- A is dupped, no change
Push(sp_r,a_r,b_r);
FlushB(write_en_r,addr_r,inc_sp,data_o,b_r); state <= st_wait;
end if;
when dec_dup_stk_b =>
-- Pop(), t=Pop(), Push(t), Push(t), Push(t)
@@ -705,6 +742,7 @@
-- B goes to A
Push(sp_r,a_r,b_r);
FlushB(write_en_r,addr_r,inc_sp,data_o,b_r); state <= st_wait;
end if;
when dec_store =>
-- a=Pop(), b=Pop(), [a]=b
@@ -934,6 +986,10 @@
b_r <= data_i;
state <= st_execute;
end if; when st_wait =>
if mem_busy_i='0' then
state <= st_execute;
end if;
when others =>
-- Undefined behavior, we shouldn't get here.
-- It only helps synthesis tools.
--- zpu_core.vhd 2009-09-07 14:56:37.000000000 +0000 +++ zpu_core-fixed.vhd 2009-09-07 14:56:17.000000000 +0000 @@ -124,6 +124,7 @@
type StateType is ( +State_Wait, State_Load2, State_Popped, State_LoadSP2, @@ -239,6 +240,8 @@ variable tNextState : InsnType; variable tDecodedOpcode : InsnArray; variable tMultResult : unsigned(wordSize*2-1 downto 0); +
variable stack : integer;
begin
if areset = '1' then
state <= State_Idle;
@@ -255,6 +258,8 @@
multB <= (others => '0');
mem_writeMask <= (others => '1');
elsif (clk'event and clk = '1') then stack := 0;
state <= State_Wait;
end if;
end if;
when State_StoreSP =>
@@ -578,6 +584,7 @@
mem_writeEnable <= '1';
mem_addr <= std_logic_vector(incSp);
mem_write <= std_logic_vector(stackB); State <= State_Wait;
end if;
when State_PopPC =>
if in_mem_busy='0' then
@@ -738,6 +745,7 @@
mem_write <= std_logic_vector(stackB);
mem_addr <= std_logic_vector(incSp);
mem_writeEnable <= '1'; State <= State_Wait;
end if;
when State_DupStackB =>
if in_mem_busy='0' then
@@ -751,6 +759,7 @@
mem_write <= std_logic_vector(stackB);
mem_addr <= std_logic_vector(incSp);
mem_writeEnable <= '1'; State <= State_Wait;
end if;
when State_Store =>
if in_mem_busy='0' then
@@ -944,6 +979,10 @@
stackB <= unsigned(mem_read);
state <= State_Execute;
end if; when State_Wait =>
if in_mem_busy='0' then
state <= State_Execute;
end if;
when others =>
sp <= (others => DontCareValue);
report "Illegal state" severity failure;
Unfortunately, there seems to be no way to attach files. Also, formatting got completely lost apparently. I'm not sure if the patches will still apply correctly.
Give me a mail address or another place to send the patches and I'll happily resubmit them.