📄 pci_mt.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: pci_mt-- File: pci_mt.vhd-- Author: Jiri Gaisler - Gaisler Research-- Modified: Alf Vaerneus - Gaisler Research-- Description: Simple PCI master and target interface------------------------------------------------------------------------------library ieee;use ieee.std_logic_1164.all;library grlib;use grlib.amba.all;use grlib.stdlib.all;use grlib.devices.all;library gaisler;use gaisler.pci.all;use gaisler.misc.all;use gaisler.pcilib.all;entity pci_mt is generic ( hmstndx : integer := 0; abits : integer := 21; device_id : integer := 0; -- PCI device ID vendor_id : integer := 0; -- PCI vendor ID master : integer := 1; -- Enable PCI Master hslvndx : integer := 0; haddr : integer := 16#F00#; hmask : integer := 16#F00#; ioaddr : integer := 16#000#; nsync : integer range 1 to 2 := 1; -- 1 or 2 sync regs between clocks oepol : integer := 0); port( rst : in std_logic; clk : in std_logic; pciclk : in std_logic; pcii : in pci_in_type; pcio : out pci_out_type; ahbmi : in ahb_mst_in_type; ahbmo : out ahb_mst_out_type; ahbsi : in ahb_slv_in_type; ahbso : out ahb_slv_out_type);end;architecture rtl of pci_mt isconstant REVISION : amba_version_type := 0;constant hconfig : ahb_config_type := ( 0 => ahb_device_reg ( VENDOR_GAISLER, GAISLER_PCISBRG, 0, REVISION, 0), 4 => ahb_membar(haddr, '0', '0', hmask), 5 => ahb_iobar (ioaddr, 16#E00#), others => zero32);constant CSYNC : integer := nsync-1;constant MADDR_WIDTH : integer := abits;constant HADDR_WIDTH : integer := 28;type pci_input_type is record ad : std_logic_vector(31 downto 0); cbe : std_logic_vector(3 downto 0); frame : std_logic; devsel : std_logic; idsel : std_logic; trdy : std_logic; irdy : std_logic; par : std_logic; stop : std_logic; rst : std_logic; gnt : std_logic;end record;type ahbs_input_type is record haddr : std_logic_vector(HADDR_WIDTH - 1 downto 0); htrans : std_logic_vector(1 downto 0); hwrite : std_logic; hsize : std_logic_vector(1 downto 0); hburst : std_logic_vector(2 downto 0); hwdata : std_logic_vector(31 downto 0); hsel : std_logic; hiosel : std_logic; hready : std_logic;end record;type pci_target_state_type is (idle, b_busy, s_data, backoff, turn_ar);type pci_master_state_type is (idle, addr, m_data, turn_ar, s_tar, dr_bus);type pci_config_command_type is record ioen : std_logic; -- I/O access enable men : std_logic; -- Memory access enable msen : std_logic; -- Master enable spcen : std_logic; -- Special cycle enable mwie : std_logic; -- Memory write and invalidate enable vgaps : std_logic; -- VGA palette snooping enable per : std_logic; -- Parity error response enable wcc : std_logic; -- Address stepping enable serre : std_logic; -- Enable SERR# driver fbtbe : std_logic; -- Fast back-to-back enableend record;type pci_config_status_type is record c66mhz : std_logic; -- 66MHz capability udf : std_logic; -- UDF supported fbtbc : std_logic; -- Fast back-to-back capability dped : std_logic; -- Data parity error detected dst : std_logic_vector(1 downto 0); -- DEVSEL timing sta : std_logic; -- Signaled target abort rta : std_logic; -- Received target abort rma : std_logic; -- Received master abort sse : std_logic; -- Signaled system error dpe : std_logic; -- Detected parity errorend record;type pci_reg_type is record addr : std_logic_vector(MADDR_WIDTH-1 downto 0); ad : std_logic_vector(31 downto 0); cbe : std_logic_vector(3 downto 0); lcbe : std_logic_vector(3 downto 0); t_state : pci_target_state_type; -- PCI target state machine m_state : pci_master_state_type; -- PCI master state machine csel : std_logic; -- Configuration chip select msel : std_logic; -- Memory hit read : std_logic; devsel : std_logic; -- PCI device select trdy : std_logic; -- Target ready irdy : std_logic; -- Master ready stop : std_logic; -- Target stop request par : std_logic; -- PCI bus parity req : std_logic; -- Master bus request oe_par : std_logic; oe_ad : std_logic; oe_trdy : std_logic; oe_devsel: std_logic; oe_ctrl : std_logic; oe_cbe : std_logic; oe_stop : std_logic; oe_frame : std_logic; oe_irdy : std_logic; oe_req : std_logic; noe_par : std_logic; noe_ad : std_logic; noe_trdy : std_logic; noe_devsel: std_logic; noe_ctrl : std_logic; noe_cbe : std_logic; noe_stop : std_logic; noe_frame : std_logic; noe_irdy : std_logic; noe_req : std_logic; request : std_logic; -- Request from Back-end frame : std_logic; -- Master frame bar0 : std_logic_vector(31 downto MADDR_WIDTH); page : std_logic_vector(31 downto MADDR_WIDTH-1); comm : pci_config_command_type; stat : pci_config_status_type; laddr : std_logic_vector(31 downto 0); ldata : std_logic_vector(31 downto 0); pwrite : std_logic; hwrite : std_logic; start : std_logic; hreq : std_logic; hreq_ack : std_logic_vector(csync downto 0); preq : std_logic_vector(csync downto 0); preq_ack : std_logic; rready : std_logic_vector(csync downto 0); wready : std_logic_vector(csync downto 0); sync : std_logic_vector(csync downto 0); pabort : std_logic; mcnt : std_logic_vector(2 downto 0); maddr : std_logic_vector(31 downto 0); mdata : std_logic_vector(31 downto 0); stop_req : std_logic;end record;type cpu_master_state_type is (idle, sync1, busy, sync2);type cpu_slave_state_type is (idle, getd, req, sync, read, sync2, t_done);type cpu_reg_type is record tdata : std_logic_vector(31 downto 0); -- Target data maddr : std_logic_vector(31 downto 0); -- Master data mdata : std_logic_vector(31 downto 0); -- Master data be : std_logic_vector(3 downto 0); m_state : cpu_master_state_type; -- AMBA master state machine s_state : cpu_slave_state_type; -- AMBA slave state machine start : std_logic_vector(csync downto 0); hreq : std_logic_vector(csync downto 0); hreq_ack : std_logic; preq : std_logic; preq_ack : std_logic_vector(csync downto 0); sync : std_logic; hwrite : std_logic; -- AHB write on PCI pabort : std_logic_vector(csync downto 0); perror : std_logic; rready : std_logic; wready : std_logic; hrdata : std_logic_vector(31 downto 0); hresp : std_logic_vector(1 downto 0); pciba : std_logic_vector(3 downto 0);end record;signal clk_int : std_logic;signal pr : pci_input_type;signal hr : ahbs_input_type;signal r, rin : pci_reg_type;signal r2, r2in : cpu_reg_type;signal dmai : ahb_dma_in_type;signal dmao : ahb_dma_out_type;signal roe_ad, rioe_ad : std_logic_vector(31 downto 0);attribute syn_preserve : boolean;attribute syn_preserve of roe_ad : signal is true; begin-- Back-end state machine (AHB clock domain) comb : process (rst, r2, r, dmao, hr, ahbsi) variable vdmai : ahb_dma_in_type; variable v : cpu_reg_type; variable request : std_logic; variable hready : std_logic; variable hresp, hsize, htrans : std_logic_vector(1 downto 0); variable p_done : std_logic; begin v := r2; vdmai.start := '0'; vdmai.burst := '0'; vdmai.size := "10"; vdmai.address := r.laddr; v.sync := '1'; vdmai.wdata := r.ldata; vdmai.write := r.pwrite; v.start(0) := r2.start(csync); v.start(csync) := r.start; v.hreq(0) := r2.hreq(csync); v.hreq(csync) := r.hreq; v.pabort(0) := r2.pabort(csync); v.pabort(csync) := r.pabort; v.preq_ack(0) := r2.preq_ack(csync); v.preq_ack(csync) := r.preq_ack; hready := '1'; hresp := HRESP_OKAY; request := '0'; hsize := "10"; htrans := "00"; p_done := r2.hreq(0) or r2.pabort(0);---- *** APB register access *** ---- --if (apbi.psel and apbi.penable and apbi.pwrite) = '1' then --v.pciba := apbi.pwdata(31 downto 28); --end if; --apbo.prdata <= r2.pciba & addzero; if hr.hiosel = '1' then if hr.hwrite = '1' then v.pciba := ahbsi.hwdata(31 downto 28); end if; v.hrdata := r2.pciba & addzero; end if;---- *** AHB MASTER *** ---- case r2.m_state is when idle => v.sync := '0'; if r2.start(0) = '1' then if r.pwrite = '1' then v.m_state := sync1; v.wready := '0'; else v.m_state := busy; vdmai.start := '1'; end if; end if; when sync1 => if r2.start(0) = '0' then v.m_state := busy; vdmai.start := '1'; end if; when busy => if dmao.active = '1' then if dmao.ready = '1' then v.rready := not r.pwrite; v.tdata := dmao.rdata; v.m_state := sync2; end if; else vdmai.start := '1'; end if; when sync2 => if r2.start(0) = '0' then v.m_state := idle; v.wready := '1'; v.rready := '0'; end if; end case;---- *** AHB MASTER END *** -------- *** AHB SLAVE *** ---- if MASTER = 1 then if (hr.hready and hr.hsel) = '1' then hsize := hr.hsize; htrans := hr.htrans; if (hr.htrans(1) and r.comm.msen) = '1' then request := '1'; end if; end if; if (request = '1' and r2.s_state = idle) then v.maddr := r2.pciba & hr.haddr; v.hwrite := hr.hwrite; case hsize is when "00" => v.be := "1110"; -- Decode byte enable when "01" => v.be := "1100"; when "10" => v.be := "0000"; when others => v.be := "1111"; end case; elsif r2.s_state = getd and r2.hwrite = '1' then v.mdata := hr.hwdata; end if; if r2.hreq(0) = '1' then v.hrdata := r.ldata; end if; if r2.preq_ack(0) = '1' then v.preq := '0'; end if; if r2.pabort(0) = '1' then v.perror := '1'; end if; if p_done = '0' then v.hreq_ack := '0'; end if; -- AHB slave state machine case r2.s_state is when idle => if request = '1' then v.s_state := getd; end if; when getd => v.s_state := req; v.preq := '1'; when req => if r2.preq_ack(0) = '1' then v.s_state := sync; end if; when sync => if r2.preq_ack(0) = '0' then v.s_state := read; end if; when read => if p_done = '1' then v.hreq_ack := '1'; v.s_state := sync2; end if; when sync2 => if p_done = '0' then v.s_state := t_done; end if; when t_done => if request = '1' then v.s_state := idle; end if; when others => v.s_state := idle; end case; if request = '1' then if r2.s_state = t_done then if r2.perror = '1' then hresp := HRESP_ERROR; else hresp := HRESP_OKAY; end if; v.perror := '0'; else hresp := HRESP_RETRY; end if; end if; if r.comm.msen = '0' then hresp := HRESP_ERROR; end if; -- Master disabled if htrans(1) = '0' then hresp := HRESP_OKAY; end if; -- Response OK for BUSY and IDLE if (hresp /= HRESP_OKAY and (hr.hready and hr.hsel) = '1') then -- insert one wait cycle hready := '0'; end if; if hr.hready = '0' then hresp := r2.hresp; end if; v.hresp := hresp; end if;---- *** AHB SLAVE END *** ---- if rst = '0' then v.s_state := idle; v.rready := '0'; v.wready := '1'; v.m_state := idle; v.preq := '0'; v.hreq_ack := '0'; v.perror := '0'; v.be := (others => '1'); v.pciba := (others => '0'); v.hresp := (others => '0'); end if; r2in <= v; dmai <= vdmai; ahbso.hready <= hready; ahbso.hresp <= hresp; ahbso.hrdata <= r2.hrdata; end process; ahbso.hconfig <= hconfig when MASTER = 1 else (others => zero32); ahbso.hsplit <= (others => '0'); ahbso.hirq <= (others => '0'); ahbso.hindex <= hslvndx;-- PCI target core (PCI clock domain) pcicomb : process(pcii.rst, pr, pcii, r, r2, roe_ad) variable v : pci_reg_type; variable chit, mhit, hit, ready, cwrite : std_logic; variable cdata, cwdata : std_logic_vector(31 downto 0); variable comp : std_logic; -- Last transaction cycle on PCI bus variable iready : std_logic; variable mto : std_logic; variable tad, mad : std_logic_vector(31 downto 0);-- variable cbe : std_logic_vector(3 downto 0); variable caddr : std_logic_vector(7 downto 2); variable voe_ad : std_logic_vector(31 downto 0); variable oe_par : std_logic; variable oe_ad : std_logic; variable oe_ctrl : std_logic; variable oe_trdy : std_logic; variable oe_devsel: std_logic; variable oe_cbe : std_logic; variable oe_stop : std_logic; variable oe_frame : std_logic; variable oe_irdy : std_logic; variable oe_req : std_logic; begin -- Process defaults v := r; v.trdy := '1'; v.stop := '1'; v.frame := '1'; v.oe_ad := '1'; v.devsel := '1'; v.oe_frame := '1'; v.irdy := '1'; v.req := '1'; voe_ad := roe_ad; v.oe_req := '0'; v.oe_cbe := '1'; v.oe_irdy := '1'; v.rready(0) := r.rready(csync); v.rready(csync) := r2.rready; v.wready(0) := r.wready(csync); v.wready(csync) := r2.wready; v.sync(0) := r.sync(csync); v.sync(csync) := r2.sync; v.preq(0) := r.preq(csync); v.preq(csync) := r2.preq;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -