From f1e2601c27757161034136c860e044b464bf27ce Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Fri, 10 Oct 2008 21:30:42 +0000 Subject: [PATCH] Added bus fifo and write fifo git-svn-id: http://moon:8086/svn/vhdl/trunk@44 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/CPUs/MIPS/src/core/mips_bui.vhd | 288 +++++++++++++++++----------- 1 file changed, 172 insertions(+), 116 deletions(-) diff --git a/lib/CPUs/MIPS/src/core/mips_bui.vhd b/lib/CPUs/MIPS/src/core/mips_bui.vhd index 0b14dec..4b2a58e 100644 --- a/lib/CPUs/MIPS/src/core/mips_bui.vhd +++ b/lib/CPUs/MIPS/src/core/mips_bui.vhd @@ -112,31 +112,36 @@ architecture behavior of bui is ); END COMPONENT; - type bus_state_t is (init, ready, i_cache_bus_access, d_cache_bus_access, uncached_bus_access); + type bus_state_t is (init, ready, i_cache_bus_access, d_cache_bus_access, uncached_bus_read); signal s, sn : bus_state_t; + signal bus_idle : std_logic; + signal busy : std_logic; signal dmem_we : unsigned(3 downto 0); signal dcache_dout : word_t; signal dcache_mem_gnt : std_logic; signal icache_mem_gnt : std_logic; - signal dmem_mem_gnt : std_logic; - signal dcache_busy2 : std_logic; + signal dmem_mem_wr_gnt : std_logic; + signal dmem_mem_rd_gnt : std_logic; + signal dcache_busy : std_logic; signal icache_busy : std_logic; signal CYC_O_icache : std_logic; signal CYC_O_dcache : std_logic; - signal CYC_O_dmem : std_logic; + signal CYC_O_dmem_rd : std_logic; + signal CYC_O_dmem_wr : std_logic; signal SRDY_I_icache : std_logic; signal SRDY_I_dcache : std_logic; signal ADDR_O_icache : word_t; signal ADDR_O_dcache : word_t; - signal ADDR_O_dmem : word_t; + signal ADDR_O_dmem_rd : word_t; + signal ADDR_O_dmem_wr : word_t; signal STB_O_icache : std_logic; signal STB_O_dcache : std_logic; - signal STB_O_dmem : std_logic; - signal DAT_I_dmem : word_t; - signal DAT_O_dmem : word_t; - signal SEL_O_dmem : unsigned(3 downto 0); - signal WE_O_dmem : std_logic; + signal STB_O_dmem_rd : std_logic; + signal STB_O_dmem_wr : std_logic; + signal DAT_I_dmem_rd : word_t; + signal DAT_O_dmem_wr : word_t; + signal SEL_O_dmem_wr : unsigned(3 downto 0); signal dcached : std_logic; signal dcache_en : std_logic; signal uncached_access : std_logic; @@ -145,75 +150,52 @@ architecture behavior of bui is signal bus_timeout_cnt : timeout_cnt_t; signal bus_timeout : std_logic; + signal bout_fifo_din : unsigned(68 downto 0); + signal bout_fifo_dout : unsigned(68 downto 0); + signal bout_fifo_re : std_logic; + signal bout_fifo_we : std_logic; + signal bout_fifo_full : std_logic; + signal bout_fifo_empty : std_logic; + signal bout_rdy : std_logic; + + alias bout_fifo_addr_in is bout_fifo_din(31 downto 0); + alias bout_fifo_data_in is bout_fifo_din(63 downto 32); + alias bout_fifo_sel_in is bout_fifo_din(67 downto 64); + alias bout_fifo_we_in is bout_fifo_din(68); + alias bout_fifo_addr_out is bout_fifo_dout(31 downto 0); + alias bout_fifo_data_out is bout_fifo_dout(63 downto 32); + alias bout_fifo_sel_out is bout_fifo_dout(67 downto 64); + alias bout_fifo_we_out is bout_fifo_dout(68); + + signal write_fifo_din : unsigned(67 downto 0); + signal write_fifo_dout : unsigned(67 downto 0); + signal write_fifo_re : std_logic; + signal write_fifo_we : std_logic; + signal write_fifo_full : std_logic; + signal write_fifo_empty : std_logic; + signal write_busy : std_logic; + + alias write_fifo_addr_in is write_fifo_din(31 downto 0); + alias write_fifo_data_in is write_fifo_din(63 downto 32); + alias write_fifo_sel_in is write_fifo_din(67 downto 64); + alias write_fifo_addr_out is write_fifo_dout(31 downto 0); + alias write_fifo_data_out is write_fifo_dout(63 downto 32); + alias write_fifo_sel_out is write_fifo_dout(67 downto 64); + begin -bus_strobe: - process(CLK_I) - begin - if rising_edge(CLK_I) then - if RST_I = '1' then - STB_O <= '0'; - elsif dmem_mem_gnt = '1' then - STB_O <= STB_O_dmem; - elsif SRDY_I_dcache = '1' then - STB_O <= STB_O_dcache; - elsif SRDY_I_icache = '1' then - STB_O <= STB_O_icache; - elsif SRDY_I = '1' then - STB_O <= '0'; - end if; - end if; - end process; - -bus_cycle: - process(CLK_I) - begin - if rising_edge(CLK_I) then - CYC_O <= '0'; - if dmem_mem_gnt = '1' then - CYC_O <= CYC_O_dmem; - elsif dcache_mem_gnt = '1' then - CYC_O <= CYC_O_dcache; - elsif icache_mem_gnt = '1' then - CYC_O <= CYC_O_icache; - end if; - end if; - end process; - -bus_out: - process(CLK_I) - begin - if rising_edge(CLK_I) then - if RST_I = '1' then --- ADDR_O <= (others => '0'); --- DAT_O <= (others => '0'); - WE_O <= '0'; - SEL_O <= (others => '0'); - elsif dmem_mem_gnt = '1' then - ADDR_O <= ADDR_O_dmem; - DAT_O <= DAT_O_dmem; - WE_O <= WE_O_dmem; - SEL_O <= SEL_O_dmem; - elsif SRDY_I_dcache = '1' then - ADDR_O <= ADDR_O_dcache; - WE_O <= '0'; - SEL_O <= (others => '0'); - elsif SRDY_I_icache = '1' then - ADDR_O <= ADDR_O_icache; - WE_O <= '0'; - SEL_O <= (others => '0'); - end if; - end if; - end process; MRDY_O <= '1'; - - SRDY_I_icache <= SRDY_I when icache_mem_gnt = '1' else '0'; - SRDY_I_dcache <= SRDY_I when dcache_mem_gnt = '1' else '0'; --- SRDY_I_dmem <= SRDY_I when dmem_mem_gnt = '1' else '0'; + CYC_O <= not bout_fifo_empty or dmem_mem_rd_gnt or dcache_mem_gnt or icache_mem_gnt; + STB_O <= not bout_fifo_empty; + ADDR_O <= bout_fifo_addr_out; + DAT_O <= bout_fifo_data_out; + SEL_O <= bout_fifo_sel_out; + WE_O <= bout_fifo_we_out; cpu_imem_rdy <= not icache_busy after 4.5 ns; - cpu_dmem_rdy <= not (CYC_O_dmem or dcache_busy2) after 4.5 ns; + busy <= CYC_O_dmem_rd or dcache_busy or (write_busy); + cpu_dmem_rdy <= not busy after 4.5 ns; inst_icache : icache GENERIC MAP @@ -238,6 +220,8 @@ inst_icache : icache cpu_busy => icache_busy ); + SRDY_I_icache <= bout_rdy and icache_mem_gnt; + inst_dcache : dcache GENERIC MAP ( @@ -261,59 +245,127 @@ inst_dcache : dcache cpu_addr => cpu_dmem_addr, cpu_din => cpu_dmem_dout, cpu_dout => dcache_dout, - cpu_busy => dcache_busy2 + cpu_busy => dcache_busy ); + SRDY_I_dcache <= bout_rdy and dcache_mem_gnt; + dcached <= '1' when cpu_dmem_addr(31 downto 28) /= X"A" else '0'; - cpu_dmem_din <= dcache_dout when uncached_access = '0' else DAT_I_dmem; - dcache_en <= cpu_dmem_en and not CYC_O_dmem; + cpu_dmem_din <= dcache_dout when uncached_access = '0' else DAT_I_dmem_rd; + dcache_en <= cpu_dmem_en and not busy; -dcache_flags: +-- Instantiate synchronous FIFO +inst_bout_fifo: entity work.fifo_sync + GENERIC MAP + ( + addr_width => 4, + data_width => 69 + ) + PORT MAP + ( + rst => RST_I, + clk => CLK_I, + we => bout_fifo_we, + re => bout_fifo_re, + fifo_full => bout_fifo_full, + fifo_empty => bout_fifo_empty, + fifo_afull => open, + fifo_aempty => open, + data_w => bout_fifo_din, + data_r => bout_fifo_dout + ); + bout_rdy <= not bout_fifo_full; + bout_fifo_re <= not bout_fifo_empty and SRDY_I; + + bout_fifo_we <= STB_O_dmem_wr when dmem_mem_wr_gnt = '1' else + STB_O_dmem_rd when dmem_mem_rd_gnt = '1' else + STB_O_dcache when dcache_mem_gnt = '1' else + STB_O_icache when icache_mem_gnt = '1' else '0'; + + + bout_fifo_data_in <= DAT_O_dmem_wr when dmem_mem_wr_gnt = '1' else (others => '-'); + + bout_fifo_addr_in <= ADDR_O_dmem_wr when dmem_mem_wr_gnt = '1' else + ADDR_O_dmem_rd when dmem_mem_rd_gnt = '1' else + ADDR_O_dcache when dcache_mem_gnt = '1' else + ADDR_O_icache when icache_mem_gnt = '1' else (others => '-'); + + bout_fifo_sel_in <= SEL_O_dmem_wr when dmem_mem_wr_gnt = '1' else (others => '0'); + bout_fifo_we_in <= '1' when dmem_mem_wr_gnt = '1' else '0'; + +-- Instantiate synchronous FIFO +inst_write_fifo: entity work.fifo_sync + GENERIC MAP + ( + addr_width => 4, + data_width => 68, + almost_full_thresh => 12, + almost_empty_thresh => 4 + ) + PORT MAP + ( + rst => RST_I, + clk => CLK_I, + we => write_fifo_we, + re => write_fifo_re, + fifo_full => write_busy, + fifo_empty => write_fifo_empty, + fifo_afull => open, + fifo_aempty => open, + data_w => write_fifo_din, + data_r => write_fifo_dout + ); + + CYC_O_dmem_wr <= not write_fifo_empty; + DAT_O_dmem_wr <= write_fifo_data_out; + ADDR_O_dmem_wr <= write_fifo_addr_out; + SEL_O_dmem_wr <= write_fifo_sel_out; + + write_fifo_data_in <= cpu_dmem_dout; + write_fifo_addr_in <= cpu_dmem_addr; + write_fifo_sel_in <= cpu_dmem_we; + write_fifo_re <= STB_O_dmem_wr; + write_fifo_we <= cpu_dmem_en and not busy and not cpu_dmem_re; + +dmem_rd_flags: process(CLK_I) begin if rising_edge(CLK_I) then uncached_access <= '0'; if RST_I = '1' then - CYC_O_dmem <= '0'; + CYC_O_dmem_rd <= '0'; else - if ACK_I = '1' and dmem_mem_gnt = '1' then - uncached_access <= not WE_O_dmem; - CYC_O_dmem <= '0'; + if ACK_I = '1' and dmem_mem_rd_gnt = '1' then + uncached_access <= '1'; + CYC_O_dmem_rd <= '0'; end if; - if cpu_dmem_en = '1' and CYC_O_dmem = '0' and dcache_busy2 = '0' then - CYC_O_dmem <= '1'; - if dcached = '1' and cpu_dmem_re = '1' then - CYC_O_dmem <= '0'; + if cpu_dmem_en = '1' and busy = '0' and cpu_dmem_re = '1' then + if dcached = '0' then + CYC_O_dmem_rd <= '1'; end if; end if; end if; end if; end process; -dcache_data: +dmem_rd_data: process(CLK_I) begin if rising_edge(CLK_I) then if RST_I = '1' then - DAT_I_dmem <= (others => '0'); - elsif ACK_I = '1' and CYC_O_dmem = '1' then - DAT_I_dmem <= DAT_I; + DAT_I_dmem_rd <= (others => '0'); + elsif ACK_I = '1' and CYC_O_dmem_rd = '1' then + DAT_I_dmem_rd <= DAT_I; end if; end if; end process; -dcache_regs: +dmem_rd_regs: process(CLK_I) begin if rising_edge(CLK_I) then - if RST_I = '1' then - WE_O_dmem <= '0'; - SEL_O_dmem <= (others => '0'); - elsif cpu_dmem_en = '1' and CYC_O_dmem = '0' and dcache_busy2 = '0' then - DAT_O_dmem <= cpu_dmem_dout; - ADDR_O_dmem <= cpu_dmem_addr; - WE_O_dmem <= not cpu_dmem_re; - SEL_O_dmem <= cpu_dmem_we; + if cpu_dmem_en = '1' and busy = '0' then + ADDR_O_dmem_rd <= cpu_dmem_addr; end if; end if; end process; @@ -331,48 +383,52 @@ bus_state_next: end process; bus_state: - process(s, CYC_O_icache, CYC_O_dcache, CYC_O_dmem, SRDY_I, ACK_I) + process(s, CYC_O_icache, CYC_O_dcache, CYC_O_dmem_wr, CYC_O_dmem_rd, bout_rdy, ACK_I) begin icache_mem_gnt <= '0'; dcache_mem_gnt <= '0'; - dmem_mem_gnt <= '0'; - STB_O_dmem <= '0'; + dmem_mem_rd_gnt <= '0'; + dmem_mem_wr_gnt <= '0'; + STB_O_dmem_rd <= '0'; + STB_O_dmem_wr <= '0'; + bus_idle <= '0'; sn <= s; case s is when init => sn <= ready; when ready => - if CYC_O_dmem = '1' then - dmem_mem_gnt <= '1'; - if SRDY_I = '1' then - STB_O_dmem <= '1'; - sn <= uncached_bus_access; + bus_idle <= '1'; + if CYC_O_dmem_wr = '1' then + dmem_mem_wr_gnt <= '1'; + if bout_rdy = '1' then + STB_O_dmem_wr <= '1'; + end if; + elsif CYC_O_dmem_rd = '1' then + dmem_mem_rd_gnt <= '1'; + if bout_rdy = '1' then + STB_O_dmem_rd <= '1'; + sn <= uncached_bus_read; end if; elsif CYC_O_icache = '1' then sn <= i_cache_bus_access; --- icache_mem_gnt <= '1'; elsif CYC_O_dcache = '1' then sn <= d_cache_bus_access; --- dcache_mem_gnt <= '1'; end if; when i_cache_bus_access => icache_mem_gnt <= '1'; if CYC_O_icache = '0' then sn <= ready; --- icache_mem_gnt <= '0'; end if; when d_cache_bus_access => dcache_mem_gnt <= '1'; if CYC_O_dcache = '0' then sn <= ready; --- dcache_mem_gnt <= '0'; end if; - when uncached_bus_access => - dmem_mem_gnt <= '1'; + when uncached_bus_read => + dmem_mem_rd_gnt <= '1'; if ACK_I = '1' then sn <= ready; --- dmem_mem_gnt <= '0'; end if; when others => sn <= ready; @@ -384,7 +440,7 @@ bus_timeout_counter: process(CLK_I) begin if rising_edge(CLK_I) then - if (icache_mem_gnt or dcache_mem_gnt or dmem_mem_gnt) = '1' then + if bus_idle = '0' then if bus_timeout_cnt /= 0 then bus_timeout_cnt <= bus_timeout_cnt - 1; else @@ -406,11 +462,11 @@ bus_err: cpu_dmem_err <= '0'; elsif bus_timeout = '1' then cpu_imem_err <= icache_mem_gnt; - cpu_dmem_err <= dcache_mem_gnt or dmem_mem_gnt; + cpu_dmem_err <= dcache_mem_gnt or dmem_mem_wr_gnt or dmem_mem_rd_gnt; end if; end if; end process; - + ------------------------------------------------------------------- end behavior;