207 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			VHDL
		
	
	
	
	
	
			
		
		
	
	
			207 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			VHDL
		
	
	
	
	
	
| library ieee;
 | |
| use ieee.std_logic_1164.all;
 | |
| use ieee.numeric_std.all;
 | |
| 
 | |
| entity sysbus is
 | |
|   port(
 | |
|         clk: in std_logic;
 | |
|         rst: in std_logic;
 | |
| 
 | |
|   -- master port 0
 | |
|         m0_addr: in std_logic_vector(15 downto 0);
 | |
|         m0_wdata: in std_logic_vector(15 downto 0);
 | |
|         m0_rdata: out std_logic_vector(15 downto 0);
 | |
|         m0_re: in std_logic;
 | |
|         m0_we: in std_logic;
 | |
|         m0_busy: out std_logic;
 | |
| 
 | |
|   -- master port 1
 | |
|         m1_addr: in std_logic_vector(15 downto 0);
 | |
|         m1_wdata: in std_logic_vector(15 downto 0);
 | |
|         m1_rdata: out std_logic_vector(15 downto 0);
 | |
|         m1_re: in std_logic;
 | |
|         m1_we: in std_logic;
 | |
|         m1_busy: out std_logic;
 | |
| 
 | |
|   -- actual bus
 | |
|         bus_addr: out std_logic_vector(15 downto 0);
 | |
|         bus_wdata: out std_logic_vector(15 downto 0);
 | |
|         bus_rdata: in std_logic_vector(15 downto 0);
 | |
|         bus_re: out std_logic;
 | |
|         bus_we: out std_logic
 | |
|       );
 | |
| end entity sysbus;
 | |
| 
 | |
| architecture behavior of sysbus is
 | |
|   type bus_state is (IDLE, READING, PENDING);
 | |
| 
 | |
|   signal owner_next, owner: std_logic_vector(0 to 1);
 | |
|   signal state_next, state: bus_state;
 | |
| 
 | |
|   signal pend_addr, pend_addr_next: std_logic_vector(15 downto 0);
 | |
|   signal pend_wdata, pend_wdata_next: std_logic_vector(15 downto 0);
 | |
|   signal pend, pend_next: std_logic_vector(0 to 1);
 | |
| 
 | |
|   signal were: std_logic_vector(0 to 3);
 | |
| begin
 | |
| 
 | |
|   were <= m0_we & m1_we & m0_re & m1_re;
 | |
| 
 | |
|   process(were, m0_addr, m0_wdata, m1_addr, m1_wdata, bus_rdata, state, owner, pend, pend_addr, pend_wdata)
 | |
|   begin
 | |
|     if pend = "00" then
 | |
|       m0_busy <= '0';
 | |
|       m1_busy <= '0';
 | |
|     else
 | |
|       m0_busy <= '1';
 | |
|       m1_busy <= '1';
 | |
|     end if;
 | |
| 
 | |
|     pend_next <= pend;
 | |
|     pend_addr_next <= pend_addr;
 | |
|     pend_wdata_next <= pend_wdata;
 | |
|     owner_next <= "00";
 | |
|     state_next <= IDLE;
 | |
| 
 | |
|     bus_we <= '0';
 | |
|     bus_re <= '0';
 | |
| 
 | |
|     -- some defaults
 | |
|     bus_addr <= x"0000";
 | |
|     bus_wdata <= x"0000";
 | |
| 
 | |
|     m0_rdata <= x"0000";
 | |
|     m1_rdata <= x"0000";
 | |
| 
 | |
|     case state is
 | |
|       when READING =>
 | |
|         if owner = "10" then
 | |
|           bus_addr <= m0_addr;
 | |
|           m0_rdata <= bus_rdata;
 | |
|           m1_busy <= '1';
 | |
|         else
 | |
|           bus_addr <= m1_addr;
 | |
|           m1_rdata <= bus_rdata;
 | |
|           m0_busy <= '1';
 | |
|         end if;
 | |
|         if pend = "00" then
 | |
|           state_next <= IDLE;
 | |
|         else
 | |
|           state_next <= PENDING;
 | |
|         end if;
 | |
| 
 | |
|       when PENDING =>
 | |
|         bus_addr <= pend_addr;
 | |
|         bus_we <= '1';
 | |
|         bus_wdata <= pend_wdata;
 | |
|         pend_next <= "00";
 | |
|         state_next <= IDLE;
 | |
| 
 | |
|       when IDLE =>
 | |
|         case were is
 | |
|           when "0000" =>
 | |
|             -- chill
 | |
|           when "1000" =>
 | |
|             bus_addr <= m0_addr;
 | |
|             bus_wdata <= m0_wdata;
 | |
|             bus_we <= '1';
 | |
|             bus_re <= '0';
 | |
|           when "0100" =>
 | |
|             bus_addr <= m1_addr;
 | |
|             bus_wdata <= m1_wdata;
 | |
|             bus_we <= '1';
 | |
|             bus_re <= '0';
 | |
|           when "1100" =>
 | |
|             bus_addr <= m0_addr;
 | |
|             bus_wdata <= m0_wdata;
 | |
|             bus_we <= '1';
 | |
|             bus_re <= '0';
 | |
| 
 | |
|             pend_next <= "01";
 | |
|             pend_addr_next <= m1_addr;
 | |
|             pend_wdata_next <= m1_wdata;
 | |
|             state_next <= PENDING;
 | |
| 
 | |
|           when "0010" =>
 | |
|             state_next <= READING;
 | |
|             owner_next <= "10";
 | |
| 
 | |
|             bus_addr <= m0_addr;
 | |
|             bus_we <= '0';
 | |
|             bus_re <= '1';
 | |
| 
 | |
|             m1_busy <= '1';
 | |
| 
 | |
|           when "0001" =>
 | |
|             state_next <= READING;
 | |
|             owner_next <= "01";
 | |
| 
 | |
|             bus_addr <= m1_addr;
 | |
|             bus_we <= '0';
 | |
|             bus_re <= '1';
 | |
| 
 | |
|             m0_busy <= '1';
 | |
| 
 | |
|           when "0011" =>
 | |
|             state_next <= READING;
 | |
|             owner_next <= "10";
 | |
| 
 | |
|             bus_addr <= m0_addr;
 | |
|             bus_we <= '0';
 | |
|             bus_re <= '1';
 | |
| 
 | |
|             m1_busy <= '1';
 | |
| 
 | |
|           when "1001" =>
 | |
|             state_next <= READING;
 | |
|             owner_next <= "01";
 | |
| 
 | |
|             bus_addr <= m1_addr;
 | |
|             bus_we <= '0';
 | |
|             bus_re <= '1';
 | |
| 
 | |
|             pend_next <= "10";
 | |
|             pend_addr_next <= m0_addr;
 | |
|             pend_wdata_next <= m0_wdata;
 | |
| 
 | |
|             m0_busy <= '1';
 | |
| 
 | |
|           when "0110" =>
 | |
|             state_next <= READING;
 | |
|             owner_next <= "10";
 | |
| 
 | |
|             bus_addr <= m0_addr;
 | |
|             bus_we <= '0';
 | |
|             bus_re <= '1';
 | |
| 
 | |
|             pend_next <= "01";
 | |
|             pend_addr_next <= m1_addr;
 | |
|             pend_wdata_next <= m1_wdata;
 | |
| 
 | |
|             m1_busy <= '1';
 | |
| 
 | |
|           when others =>
 | |
|             -- blarg
 | |
|         end case;
 | |
|     end case;
 | |
|   end process;
 | |
| 
 | |
|   process(clk, rst)
 | |
|   begin
 | |
|     if rst = '1' then
 | |
|       state <= IDLE;
 | |
|       owner <= "00";
 | |
|       pend <= "00";
 | |
|       pend_addr <= x"0000";
 | |
|       pend_wdata <= x"0000";
 | |
|     elsif rising_edge(clk) then
 | |
|       state <= state_next;
 | |
|       owner <= owner_next;
 | |
|       pend <= pend_next;
 | |
|       pend_addr <= pend_addr_next;
 | |
|       pend_wdata <= pend_wdata_next;
 | |
|     end if;
 | |
|   end process;
 | |
| 
 | |
| end behavior;
 |