📄 pcitb_target.vhd
字号:
-------------------------------------------------------------------------------- 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_target-- File: pcitb_target.vhd-- Author: Alf Vaerneus, Gaisler Research-- Description: PCI Target emulator.-------------------------------------------------------------------------------- pragma translate_offlibrary ieee;use ieee.std_logic_1164.all;library grlib;use grlib.stdlib.all;library gaisler;use gaisler.pcitb.all;use gaisler.pcilib.all;use gaisler.ambatest.all;library std;use std.textio.all;entity pcitb_target is generic ( slot : integer := 0; abits : integer := 10; bars : integer := 1; resptime : integer := 2; latency : integer := 0; rbuf : integer := 8; stopwd : boolean := true; tval : time := 7 ns; conf : config_header_type := config_init; 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_target;architecture tb of pcitb_target isconstant T_O : integer := 9;constant word : std_logic_vector(2 downto 0) := "100";type mem_type is array(0 to ((2**abits)-1)) of std_logic_vector(31 downto 0);type state_type is(idle,respwait,write,read,latw);type reg_type is record state : state_type; pci : pci_type; pcien : std_logic; aden : std_logic; paren : std_logic; erren : std_logic; write : std_logic; waitcycles : integer; latcnt : integer; curword : integer; first : boolean; di : std_logic_vector(31 downto 0); ad : std_logic_vector(31 downto 0); comm : std_logic_vector(3 downto 0); config : config_header_type;end record;signal r,rin : reg_type;signal do : std_logic_vector(31 downto 0);procedure writeconf(ad : in std_logic_vector(5 downto 0); data : in std_logic_vector(31 downto 0); vconfig : out config_header_type) isbegin case conv_integer(ad) is-- when 0 => vconfig.devid := data(31 downto 16); vconfig.vendid <= data(15 downto 0); when 1 => vconfig.status := data(31 downto 16); vconfig.command := data(15 downto 0); when 2 => vconfig.class_code := data(31 downto 8); vconfig.revid := data(7 downto 0); when 3 => vconfig.bist := data(31 downto 24); vconfig.header_type := data(23 downto 16); vconfig.lat_timer := data(15 downto 8); vconfig.cache_lsize := data(7 downto 0); when 4 => vconfig.bar(0) := data; when 5 => vconfig.bar(1) := data; when 6 => vconfig.bar(2) := data; when 7 => vconfig.bar(3) := data; when 8 => vconfig.bar(4) := data; when 9 => vconfig.bar(5) := data; when 10 => vconfig.cis_p := data; when 11 => vconfig.subid := data(31 downto 16); vconfig.subvendid := data(15 downto 0); when 12 => vconfig.exp_rom_ba := data; when 13 => vconfig.max_lat := data(31 downto 24); vconfig.min_gnt := data(23 downto 16); vconfig.int_pin := data(15 downto 8); vconfig.int_line := data(7 downto 0); when others => end case;end procedure;procedure readconf(ad : in std_logic_vector(5 downto 0); data : out std_logic_vector(31 downto 0)) isbegin case conv_integer(ad) is when 0 => data(31 downto 16) := (conv_std_logic_vector(slot,4) & r.config.devid(11 downto 0)); data(15 downto 0) := r.config.vendid; when 1 => data(31 downto 16) := r.config.status; data(15 downto 0) := r.config.command; when 2 => data(31 downto 8) := r.config.class_code; data(7 downto 0) := r.config.revid; when 3 => data(31 downto 24) := r.config.bist; data(23 downto 16) := r.config.header_type; data(15 downto 8) := r.config.lat_timer; data(7 downto 0) := r.config.cache_lsize; when 4 => data := r.config.bar(0)(31 downto abits) & zero32(abits-1 downto 0); when 5 => if bars > 1 then data := r.config.bar(1)(31 downto 9) & zero32(8 downto 1) & '1'; else data := (others => '0'); end if; when 6 => if bars > 2 then data := r.config.bar(2)(31 downto abits) & zero32(abits-1 downto 0); else data := (others => '0'); end if; when 7 => if bars > 3 then data := r.config.bar(3)(31 downto abits) & zero32(abits-1 downto 0); else data := (others => '0'); end if; when 8 => if bars > 4 then data := r.config.bar(4)(31 downto abits) & zero32(abits-1 downto 0); else data := (others => '0'); end if; when 9 => if bars > 5 then data := r.config.bar(5)(31 downto abits) & zero32(abits-1 downto 0); else data := (others => '0'); end if; when 10 => data := r.config.cis_p; when 11 => data(31 downto 16) := r.config.subid; data(15 downto 0) := r.config.subvendid; when 12 => data := r.config.exp_rom_ba; when 13 => data(31 downto 24) := r.config.max_lat; data(23 downto 16) := r.config.min_gnt; data(15 downto 8) := r.config.int_pin; data(7 downto 0) := r.config.int_line; when others => end case;end procedure;function pci_hit(ad : std_logic_vector(31 downto 0); c : std_logic_vector(3 downto 0); idsel : std_logic; con : config_header_type) return boolean isvariable hit : boolean;begin hit := false; if ((c = CONF_READ or c = CONF_WRITE) and idsel = '1' and ad(1 downto 0) = "00") then hit := true; else for i in 0 to bars loop if i = 1 then if ((c = IO_READ or c = IO_WRITE) and ad(31 downto abits) = con.bar(i)(31 downto abits)) then hit := true; end if; else if ((c = MEM_READ or c = MEM_WRITE or c = MEM_R_MULT or c = MEM_R_LINE or c = MEM_W_INV) and ad(31 downto abits) = con.bar(i)(31 downto abits)) then hit := true; end if; end if; end loop; end if; return(hit);end function;begin cont : process file readfile,writefile : text; variable first : boolean := true; variable mem : mem_type; variable L : line; variable datahex : string(1 to 8); variable count : integer; begin if first then for i in 0 to ((2**abits)-1) loop mem(i) := (others => '0'); end loop; first := false; elsif tbi.start = '1' then if tbi.usewfile then file_open(writefile, external_name => tbi.wfile(18 downto trimlen(tbi.wfile)), open_kind => write_mode); count := conv_integer(tbi.address); for i in 0 to tbi.no_words-1 loop write(L,printhex(mem(count),32)); writeline(writefile,L); count := count+4; end loop; file_close(writefile); end if; elsif r.ad(0) /= 'U' then do <= mem(conv_integer(to_x01(r.ad))); if r.write = '1' then mem(conv_integer(to_x01(r.ad))) := r.di; end if; end if; tbo.ready <= tbi.start; wait for 1 ns; end process; comb : process(pciin, do) variable v : reg_type; begin v := r; v.write := '0'; v.pci.ad.par := xorv(r.pci.ad.ad & pciin.ad.cbe); v.paren := r.aden; v.erren := r.paren; case r.state is when idle => if (r.pci.ifc.trdy and r.pci.ifc.stop and r.pci.ifc.devsel) = '1' then v.pcien := '1'; end if; v.aden := '1'; v.waitcycles := 1; v.latcnt := latency; v.first := true; v.pci.ifc.trdy := '1'; v.pci.ifc.stop := '1'; v.curword := 0; v.pci.ifc.devsel := '1'; v.pci.err.perr := '1'; if pciin.ifc.frame = '0' then v.comm := pciin.ad.cbe; if pci_hit(pciin.ad.ad,pciin.ad.cbe,pciin.ifc.idsel(slot),v.config) then v.ad := zero32(31 downto abits) & pciin.ad.ad(abits-1 downto 0); if r.waitcycles = resptime then v.pci.ifc.devsel := '0'; v.pcien := '0'; if pciin.ad.cbe(0) = '1' then v.state := write; v.pci.ifc.trdy := '0'; else v.state := read; v.aden := '0'; end if; else v.state := respwait; v.waitcycles := r.waitcycles+1; end if; end if; end if; when respwait => -- Initial response time if r.waitcycles = resptime then v.pci.ifc.devsel := '0'; v.pcien := '0'; if r.comm(0) = '1' then v.state := write; v.pci.ifc.trdy := '0'; else v.state := read; v.aden := '0'; end if; else v.waitcycles := r.waitcycles+1; end if; when write => -- Write access if pciin.ifc.irdy = '0' then v.curword := r.curword+1; if r.comm = CONF_WRITE then writeconf(r.ad(7 downto 2),pciin.ad.ad,v.config); else v.di := pciin.ad.ad; v.write := '1'; end if; end if; if r.write = '1' then v.ad := r.ad + "100"; end if; if pciin.ifc.frame = '1' then v.state := idle; v.pci.ifc.trdy := '1'; v.pci.ifc.devsel := '1'; elsif (r.latcnt > 0 and pciin.ifc.irdy = '0') then v.state := latw; v.pci.ifc.trdy := '1'; v.latcnt := r.latcnt-1; end if; when read => -- Read access v.pci.ifc.trdy := '0'; if (pciin.ifc.irdy = '0' or r.first = true) then v.ad := r.ad + "100"; v.first := false; if r.comm = CONF_READ then readconf(r.ad(7 downto 2),v.pci.ad.ad); else v.pci.ad.ad := do; end if; end if; if (pciin.ifc.trdy or pciin.ifc.irdy) = '0' then v.curword := r.curword+1; end if; if (pciin.ifc.frame and not (pciin.ifc.trdy and pciin.ifc.stop)) = '1' then v.state := idle; v.aden := '1'; v.pci.ifc.trdy := '1'; v.pci.ifc.devsel := '1'; elsif (r.latcnt > 0 and (pciin.ifc.trdy or pciin.ifc.irdy) = '0' and pciin.ifc.stop = '1') then v.state := latw; v.latcnt := r.latcnt-1; v.pci.ifc.trdy := '1'; end if; when latw => -- Latency between data phases v.pci.ifc.trdy := '1'; if r.write = '1' then v.ad := r.ad + "100"; end if; if (r.latcnt <= 1 and r.comm(0) = '0') then v.latcnt := latency; v.state := read; v.aden := '0'; elsif r.latcnt = 0 then v.latcnt := latency; v.state := write; v.pci.ifc.trdy := '0'; else v.latcnt := r.latcnt-1; end if; when others => end case; -- Disconnect type if ((v.curword+1) >= rbuf) then if pciin.ifc.frame = '1' then v.pci.ifc.stop := '1'; elsif stopwd then if r.pci.ifc.stop = '1' then v.pci.ifc.stop := v.pci.ifc.trdy; else if pciin.ifc.irdy = '0' then v.pci.ifc.trdy := '1'; end if; v.pci.ifc.stop := '0'; end if; else v.pci.ifc.stop := '0'; v.pci.ifc.trdy := '1'; end if; end if; if pciin.syst.rst = '0' then v.state := idle; v.config := conf; v.waitcycles := 1; v.latcnt := latency; v.ad := (others => '0'); v.di := (others => '0'); end if; rin <= v; end process; clockreg : process(pciin.syst) begin if rising_edge(pciin.syst.clk) then r <= rin; end if; end process; pciout.ad.ad <= r.pci.ad.ad after tval when r.aden = '0' else (others => 'Z') after tval; pciout.ad.par <= r.pci.ad.par after tval when (r.paren = '0' and (r.pci.ad.par = '1' or r.pci.ad.par = '0')) else 'Z' after tval; pciout.ifc.trdy <= r.pci.ifc.trdy after tval when r.pcien = '0' else 'Z' after tval; pciout.ifc.stop <= r.pci.ifc.stop after tval when r.pcien = '0' else 'Z' after tval; pciout.ifc.devsel <= r.pci.ifc.devsel after tval when r.pcien = '0' else 'Z' after tval; pciout.err.perr <= r.pci.err.perr after tval when r.erren = '0' else 'Z' after tval;end;-- pragma translate_on
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -