OpenCores
URL https://opencores.org/ocsvn/layer2/layer2/trunk

Subversion Repositories layer2

[/] [layer2/] [trunk/] [vhdl/] [cpu/] [rtl/] [wbm.vhd] - Rev 2

Compare with Previous | Blame | View Log

--------------------------------------------------------------------------------
-- MIPS™ I CPU - Wishbone Master                                              --
--------------------------------------------------------------------------------
--                                                                            --
-- KNOWN BUGS:                                                                --
--                                                                            --
--  o The master cause some severe trouble when communicating with slave      --
--    interfaces that run on a different frequency than the master itself.    --
--       In order to get the DDR to work with a 50 MHz master, I added an     --
--    interface solely running at 50 MHz while the remaining DDR controller   --
--    runs at 25 MHz.                                                         --
--                                                                            --
--------------------------------------------------------------------------------
-- Copyright (C)2011  Mathias Hörtnagl <mathias.hoertnagl@gmail.comt>         --
--                                                                            --
-- This program is free software: you can redistribute it and/or modify       --
-- it under the terms of the GNU General Public License as published by       --
-- the Free Software Foundation, either version 3 of the License, or          --
-- (at your option) any later version.                                        --
--                                                                            --
-- This program is distributed in the hope that it will be useful,            --
-- but WITHOUT ANY WARRANTY; without even the implied warranty of             --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              --
-- GNU General Public License for more details.                               --
--                                                                            --
-- You should have received a copy of the GNU General Public License          --
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.      --
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
library work;
use work.iwb.all;
use work.icpu.all;
 
entity wbm is
   port(
      mi  : in  master_in_t;
      mo  : out master_out_t;
   -- Non Wishbone Signals
      ci  : out cpu_in_t;
      co  : in  cpu_out_t;
      irq : in  std_logic_vector(7 downto 0)
   );
end wbm;
 
architecture rtl of wbm is
 
   type state_t is (Init, I0, I1, I2, D0, D1, D2, Cpu);
 
   type regs_t is
   record
      s : state_t;
      i : std_logic_vector(31 downto 0);
      d : std_logic_vector(31 downto 0);
   end record;
 
   constant regs_d : regs_t := 
      regs_t'( Init, (others => '0'), (others => '0') );
 
   signal r, rin : regs_t := regs_d;
begin
 
   ci.clk <= mi.clk;
   ci.rst <= mi.rst;
 
   process(irq, r, co, mi.ack, mi.dat)
 
      variable t2 : std_logic_vector(31 downto 0);
   begin
 
      rin <= r;
 
      t2 := (others => '0');
 
      ci.hld <= '1';
      ci.ins <= (others => '0');       -- AREA: (others => '-');
      ci.dat <= (others => '0');       -- AREA: (others => '-');
      ci.irq <= irq;
 
      mo.adr <= (others => '0');       -- AREA: (others => '-');
      mo.dat <= (others => '0');       -- AREA: (others => '-');
      mo.we  <= '0';
      mo.sel <= (others => '0');
      mo.stb <= '0';
 
      case r.s is
 
         when Init =>
            rin.s <= I0;
 
         -----------------------------------------------------------------------
         -- Instruction                                                       --
         -----------------------------------------------------------------------        
         -- First stage of instruction fetch. Wait for memory device to be done
         -- loading desired data.
         when I0 =>
            mo.adr <= co.iadr;
            mo.sel <= "1111";
            mo.stb <= '1';
            if mi.ack = '1' then
               --rin.i <= mi.dat;
               rin.s <= I1;
            end if;
 
         -- Latch fetched instruction.
         -- If co.sel is not null, there is data to be processed from the memory
         -- stage. Else directly execute instruction.
         when I1 =>
            mo.adr <= co.iadr;
            mo.sel <= "1111";
            mo.stb <= '1';
            rin.i  <= mi.dat;
            rin.s  <= I2; 
 
         when I2 =>
            if mi.ack = '0' then
               if co.sel = x"0" then
                  rin.s <= Cpu;
               else
                  rin.s <= D0;
               end if;               
            end if;
 
         -----------------------------------------------------------------------
         -- Data                                                              --
         -----------------------------------------------------------------------            
         -- Set data to be written to propper location on the 32bit bus, 
         -- according to co.sel.
         -- Wait until I/O device is ready.
         when D0 =>
            mo.adr <= co.dadr;
            case co.sel is
               when "0001" => mo.dat(7 downto 0)   <= co.dat(7 downto 0);
               when "0010" => mo.dat(15 downto 8)  <= co.dat(7 downto 0);
               when "0100" => mo.dat(23 downto 16) <= co.dat(7 downto 0);
               when "1000" => mo.dat(31 downto 24) <= co.dat(7 downto 0);
               when "0011" => mo.dat(15 downto 0)  <= co.dat(15 downto 0);
               when "1100" => mo.dat(31 downto 16) <= co.dat(15 downto 0);
               when others => mo.dat               <= co.dat;
            end case;
            mo.we  <= co.we;
            mo.sel <= co.sel;
            mo.stb <= '1';
            if mi.ack = '1' then
               rin.s <= D1;
            end if;
 
         -- Finish write cycle or latch read data.
         when D1 =>
            mo.adr <= co.dadr;
 
            -- Read.
            case co.sel is
               when "0001" => t2(7 downto 0)  := mi.dat(7 downto 0);
               when "0010" => t2(7 downto 0)  := mi.dat(15 downto 8);
               when "0100" => t2(7 downto 0)  := mi.dat(23 downto 16);
               when "1000" => t2(7 downto 0)  := mi.dat(31 downto 24);
               when "0011" => t2(15 downto 0) := mi.dat(15 downto 0);
               when "1100" => t2(15 downto 0) := mi.dat(31 downto 16);
               when others => t2              := mi.dat;
            end case;
 
            -- Write.
            case co.sel is
               when "0001" => mo.dat(7 downto 0)   <= co.dat(7 downto 0);
               when "0010" => mo.dat(15 downto 8)  <= co.dat(7 downto 0);
               when "0100" => mo.dat(23 downto 16) <= co.dat(7 downto 0);
               when "1000" => mo.dat(31 downto 24) <= co.dat(7 downto 0);
               when "0011" => mo.dat(15 downto 0)  <= co.dat(15 downto 0);
               when "1100" => mo.dat(31 downto 16) <= co.dat(15 downto 0);
               when others => mo.dat               <= co.dat;
            end case;
 
            mo.we  <= co.we;
            mo.sel <= co.sel;
            mo.stb <= '1';
            rin.d  <= t2;
            rin.s  <= D2;
 
         when D2 =>
            if mi.ack = '0' then
               rin.s <= Cpu;
            end if;
 
         -----------------------------------------------------------------------
         -- Run CPU                                                           --
         -----------------------------------------------------------------------             
         -- Enable CPU and run it for one cycle, then at least fetch the next 
         -- instruction.
         when Cpu =>
            ci.hld <= '0';
            ci.ins <= r.i;
            ci.dat <= r.d;
            rin.s  <= I0;
      end case;
   end process;
 
   reg : process(mi.clk)
   begin
      if rising_edge(mi.clk) then        
         if mi.rst = '1' then r <= regs_d; else r <= rin; end if;
      end if;
   end process;
end architecture;

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.