OpenCores

ZPU - the worlds smallest 32 bit CPU with GCC toolchain

Issue List
ZPU fails running from slow RAM #1
Open crazor opened this issue over 15 years ago
crazor commented over 15 years ago

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

crazor commented over 15 years ago

--- 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.
crazor commented over 15 years ago

--- 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;
  • -- we must multiply unconditionally to get pipelined multiplication tMultResult := multA * multB; multResult3 <= multResult2; @@ -491,6 +496,7 @@ stackA(i) <= opcode(to_integer(pc(byteBits-1 downto 0)))(6); end loop; stackA(6 downto 0) <= unsigned(opcode(to_integer(pc(byteBits-1 downto 0)))(6 downto 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;
crazor commented over 15 years ago

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.


Assignee
No one
Labels
Bug