URL
https://opencores.org/ocsvn/mips_enhanced/mips_enhanced/trunk
Subversion Repositories mips_enhanced
[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [lib/] [gaisler/] [pci/] [pcitb_master.vhd] - Rev 2
Compare with Previous | Blame | View Log
------------------------------------------------------------------------------ -- This file is a part of the GRLIB VHDL IP LIBRARY -- Copyright (C) 2003, Gaisler Research -- -- 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 2 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, write to the Free Software -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ----------------------------------------------------------------------------- -- Entity: pcitb_master -- File: pcitb_master.vhd -- Author: Alf Vaerneus, Gaisler Research -- Description: PCI Master emulator. Can act as a system host ------------------------------------------------------------------------------ -- pragma translate_off library ieee; use ieee.std_logic_1164.all; library std; use std.textio.all; library grlib; use grlib.stdlib.all; library gaisler; use gaisler.pcitb.all; use gaisler.pcilib.all; use gaisler.ambatest.all; library grlib; use grlib.stdlib.xorv; entity pcitb_master is generic ( slot : integer := 0; tval : time := 7 ns; dbglevel : integer := 1); port ( -- PCI signals pciin : in pci_type; pciout : out pci_type; -- TB signals tbi : in tb_in_type; tbo : out tb_out_type ); end pcitb_master; architecture tb of pcitb_master is constant T_O : integer := 9; type filedata_type is record address : std_logic_vector(31 downto 0); data : std_logic_vector(31 downto 0); command : std_logic_vector(3 downto 0); last : std_logic; openrfile : std_logic; openwfile : std_logic; end record; type state_type is(idle,active,done); type reg_type is record state : state_type; pcien : std_logic_vector(3 downto 0); paren : std_logic; read : std_logic; burst : std_logic; grant : std_logic; address : std_logic_vector(31 downto 0); data : std_logic_vector(31 downto 0); current_word : natural; tocnt : integer; running : std_logic; pci : pci_type; status : status_type; end record; signal r,rin : reg_type; signal filedata : filedata_type; begin comb : process(pciin) variable vpci : pci_type; variable v : reg_type; variable i,count,dataintrans : integer; variable status : status_type; variable ready,stop : std_logic; variable comm : std_logic_vector(3 downto 0); begin v := r; count := count+1; v.tocnt := 0; ready := '0'; stop := '0'; v.pcien(0) := '1'; v.pcien(3 downto 1) := r.pcien(2 downto 0); if tbi.start = '1' then if (r.running = '0' and r.state = idle) then v.address := tbi.address(31 downto 2) & "00"; status := OK; v.running := '1'; end if; case tbi.command is when M_READ => v.burst := '0'; v.read := '1'; comm := MEM_READ; when M_READ_MULT => v.burst := '1'; v.read := '1'; comm := MEM_R_MULT; when M_READ_LINE => v.burst := '1'; v.read := '1'; comm := MEM_R_LINE; when M_WRITE => if tbi.no_words = 1 then v.burst := '0'; else v.burst := '1'; end if; v.read := '0'; comm := MEM_WRITE; when M_WRITE_INV => v.burst := '1'; v.read := '0'; comm := MEM_W_INV; when C_READ => v.burst := '0'; v.read := '1'; comm := CONF_READ; when C_WRITE => v.burst := '0'; v.read := '0'; comm := CONF_WRITE; when others => end case; if not tbi.userfile then v.pci.ad.ad := tbi.data; end if; end if; if tbi.userfile then v.address := (filedata.address(31 downto 2) + conv_std_logic_vector(v.current_word,30)) & "00"; comm := filedata.command; v.pci.ad.ad := filedata.data; v.burst := not filedata.last; stop := filedata.last; end if; v.pci.ad.par := xorv(r.pci.ad.ad & r.pci.ad.cbe); v.paren := r.read; if (pciin.ifc.devsel and not pciin.ifc.stop) = '1' and r.running = '1' then status := ERR; elsif r.tocnt = T_O then status := TIMEOUT; else status := OK; end if; case r.state is when idle => v.pci.arb.req(slot) := not (r.running and r.pcien(1)); v.pci.ifc.irdy := '1'; dataintrans := 0; if r.grant = '1' then v.state := active; v.pci.ifc.frame := '0'; v.read := '0'; v.pcien(0) := '0'; v.pci.ad.ad := v.address; v.pci.ad.cbe := comm; end if; when active => v.tocnt := r.tocnt + 1; v.pcien(0) := '0'; v.pci.ifc.irdy := '0'; v.pci.ad.cbe := (others => '0'); v.pci.arb.req(slot) := not (r.burst and not pciin.ifc.frame); if (pciin.ifc.irdy or (pciin.ifc.trdy and pciin.ifc.stop)) = '0' then if pciin.ifc.trdy = '0' then v.current_word := r.current_word+1; v.data := pciin.ad.ad; dataintrans := dataintrans+1; end if; end if; if pciin.ifc.devsel = '0' then v.tocnt := 0; end if; if ((v.current_word+conv_integer(r.burst)) >= tbi.no_words and tbi.userfile = false) then stop := '1'; if pciin.ifc.frame = '1' then if pciin.ifc.trdy = '0' then v.running := '0'; v.pci.ifc.irdy := '1'; v.pcien(0) := '1'; elsif (pciin.ifc.trdy and not pciin.ifc.stop) = '1' then v.state := idle; v.pci.ifc.irdy := '1'; v.pcien(0) := '1'; if dataintrans > 0 then v.address := (tbi.address(31 downto 2) + conv_std_logic_vector(v.current_word,30)) & "00"; end if; end if; end if; elsif pciin.ifc.stop = '0' then v.pcien(0) := pciin.ifc.frame; stop := '1'; v.state := idle; v.pci.ifc.irdy := pciin.ifc.frame; if not tbi.userfile then v.address := (tbi.address(31 downto 2) + conv_std_logic_vector(v.current_word,30)) & "00"; end if; end if; -- if (status /= OK or (r.running = '0' and ((pciin.ifc.irdy or not (pciin.ifc.trdy and pciin.ifc.stop)) = '1' or tbi.userfile = true))) then if (r.status /= OK or ((pciin.ifc.frame and not pciin.ifc.irdy and not pciin.ifc.trdy) = '1')) then v.state := done; v.pci.ifc.irdy := '1'; v.pcien(0) := '1'; v.pci.arb.req(slot) := '1'; end if; v.pci.ifc.frame := not (r.burst and not stop); when done => v.running := '0'; ready := '1'; if tbi.start = '0' then v.state := idle; v.current_word := 0; end if; when others => end case; v.grant := to_x01(pciin.ifc.frame) and to_x01(pciin.ifc.irdy) and not r.pci.arb.req(slot) and not to_x01(pciin.arb.gnt(slot)); if pciin.syst.rst = '0' then v.pcien := (others => '1'); v.state := idle; v.read := '0'; v.burst := '0'; v.grant := '0'; v.address := (others => '0'); v.data := (others => '0'); v.current_word := 0; v.running := '0'; v.pci := pci_idle; end if; tbo.ready <= ready; v.status := status; tbo.status <= status; tbo.data <= r.data; rin <= v; end process; clockreg : process(pciin.syst) file readfile,writefile : text; variable L : line; variable datahex : string(1 to 8); variable count : integer; begin if pciin.syst.rst = '0' then filedata.address <= (others => '0'); filedata.data <= (others => '0'); filedata.command <= (others => '0'); filedata.last <= '0'; filedata.openrfile <= '0'; filedata.openwfile <= '0'; elsif rising_edge(pciin.syst.clk) then -- r <= rin; if tbi.usewfile then case r.state is when idle => if (tbi.start and not filedata.openwfile) = '1' then file_open(writefile, external_name => tbi.wfile(18 downto trimlen(tbi.wfile)), open_kind => write_mode); filedata.openwfile <= '1'; count := 0; end if; when active => if (pciin.ifc.trdy or pciin.ifc.irdy) = '0' then if (tbi.userfile = false or count > 0) then write(L,printhex(pciin.ad.ad,32)); writeline(writefile,L); end if; count := count+1; end if; if rin.state = done then file_close(writefile); filedata.openwfile <= '0'; end if; when others => end case; end if; if tbi.userfile then case r.state is when idle => if (tbi.start and not filedata.openrfile) = '1' then filedata.last <= '0'; filedata.openrfile <= '1'; file_open(readfile,external_name => tbi.rfile(18 downto trimlen(tbi.rfile)), open_kind => read_mode); readline(readfile,L); -- Dummy read for header readline(readfile,L); read(L,datahex); filedata.address <= conv_std_logic_vector(datahex,32); readline(readfile,L); read(L,datahex); filedata.command <= conv_std_logic_vector(datahex,4); readline(readfile,L); -- Dummy read for header readline(readfile,L); read(L,datahex); filedata.data <= conv_std_logic_vector(datahex,32); end if; when active => if (pciin.ifc.trdy or pciin.ifc.irdy) = '0' then if not endfile(readfile) then readline(readfile,L); read(L,datahex); filedata.data <= conv_std_logic_vector(datahex,32); r.pci.ad.ad <= conv_std_logic_vector(datahex,32); end if; if endfile(readfile) then filedata.last <= '1'; r.pci.ifc.frame <= '1'; r.running <= '0'; end if; end if; when done => if tbi.start = '0' then file_close(readfile); filedata.openrfile <= '0'; end if; when others => end case; end if; end if; if rising_edge(pciin.syst.clk) then r <= rin; end if; end process; pciout.ad.ad <= r.pci.ad.ad after tval when (r.read or r.pcien(0)) = '0' else (others => 'Z') after tval; pciout.ad.cbe <= r.pci.ad.cbe after tval when r.pcien(0) = '0' else (others => 'Z') after tval; pciout.ad.par <= r.pci.ad.par after tval when (r.paren or r.pcien(1)) = '0' else 'Z' after tval; pciout.ifc.frame <= r.pci.ifc.frame after tval when r.pcien(0) = '0' else 'Z' after tval; pciout.ifc.irdy <= r.pci.ifc.irdy after tval when r.pcien(1) = '0' else 'Z' after tval; pciout.err.perr <= r.pci.err.perr after tval when r.pcien(2) = '0' else 'Z' after tval; pciout.err.serr <= r.pci.err.serr after tval when r.pcien(2) = '0' else 'Z' after tval; pciout.arb.req(slot) <= r.pci.arb.req(slot) after tval; end; -- pragma translate_on