pci_mtf.vhd
来自「The GRLIB IP Library is an integrated se」· VHDL 代码 · 共 1,463 行 · 第 1/4 页
VHD
1,463 行
------------------------------------------------------------------------------ This file is a part of the GRLIB VHDL IP LIBRARY-- Copyright (C) 2004 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.---- See the file COPYING for the full details of the license.--------------------------------------------------------------------------------- Entity: pci_mtf-- File: pci_mtf.vhd-- Author: Jiri Gaisler - Gaisler Research-- Modified: Alf Vaerneus - Gaisler Research-- Description: 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.tech.all;library gaisler;use gaisler.devices.all;use gaisler.memory.all;use gaisler.pci.all;use gaisler.pcilib.all;use gaisler.misc.all;entity pci_mtf is generic ( memtech : integer := DEFMEMTECH; hmstndx : integer := 0; dmamst : integer := NAHBMST; readpref : integer := 0; abits : integer := 21; dmaabits : integer := 26; fifodepth : integer := 3; -- FIFO depth device_id : integer := 0; -- PCI device ID vendor_id : integer := 0; -- PCI vendor ID master : integer := 1; -- Enable PCI Master hslvndx : integer := 0; pindex : integer := 0; paddr : integer := 0; pmask : integer := 16#fff#; haddr : integer := 16#F00#; hmask : integer := 16#F00#; ioaddr : integer := 16#000#; nsync : integer range 1 to 2 := 2; -- 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; apbi : in apb_slv_in_type; apbo : out apb_slv_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_mtf isconstant REVISION : amba_version_type := 0;constant CSYNC : integer := nsync-1;constant HADDR_WIDTH : integer := 28;constant MADDR_WIDTH : integer := abits;constant DMAMADDR_WIDTH : integer := dmaabits;constant FIFO_DEPTH : integer := fifodepth;constant FIFO_FULL : std_logic_vector(FIFO_DEPTH - 2 downto 0) := (others => '1');constant FIFO_DATA_BITS : integer := 32; -- One valid bitconstant NO_CPU_REGS : integer := 6;constant NO_PCI_REGS : integer := 6;constant pconfig : apb_config_type := ( 0 => ahb_device_reg ( VENDOR_GAISLER, GAISLER_PCIFBRG, 0, REVISION, 0), 1 => apb_iobar(paddr, pmask));constant hconfig : ahb_config_type := ( 0 => ahb_device_reg ( VENDOR_GAISLER, GAISLER_PCIFBRG, 0, REVISION, 0), 4 => ahb_membar(haddr, '0', '0', hmask), 5 => ahb_iobar (ioaddr, 16#E00#), others => zero32);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; host : std_logic;end record;type pci_fifo_in_type is record ren : std_logic; raddr : std_logic_vector(FIFO_DEPTH - 1 downto 0); wen : std_logic; waddr : std_logic_vector(FIFO_DEPTH - 1 downto 0); wdata : std_logic_vector(FIFO_DATA_BITS - 1 downto 0);end record;type pci_fifo_out_type is record rdata : std_logic_vector(FIFO_DATA_BITS - 1 downto 0);end record;type fifo_type is record side : std_logic; -- Owner access side. Receiver accesses the other side raddr : std_logic_vector(FIFO_DEPTH - 2 downto 0); waddr : std_logic_vector(FIFO_DEPTH - 2 downto 0);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_master_fifo_state_type is (idle, addr, incr, last1, sync, t_retry, ttermwd, ttermnd, abort, done, wdone);type pci_target_type is record state : pci_target_state_type; cnt : std_logic_vector(2 downto 0); csel : std_logic; -- Configuration chip select msel : std_logic; -- Memory hit barsel : std_logic; -- Memory hit psel : std_logic; -- Page hit addr : std_logic_vector(31 downto 0); laddr : std_logic_vector(31 downto 0); lsize : std_logic_vector(1 downto 0); lwrite : std_logic; lburst : std_logic; lmult : std_logic; mult : std_logic; read : std_logic; -- PCI target read burst : std_logic; pending : std_logic; wdel : std_logic; last : std_logic; fifo : fifo_type;end record;type pci_master_type is record state : pci_master_state_type; fstate : pci_master_fifo_state_type; cnt : std_logic_vector(2 downto 0); ltim : std_logic_vector(7 downto 0); -- Latency timer request : std_logic; hwrite : std_logic; stop_req : std_logic; last : std_logic; valid : std_logic; split : std_logic; first : std_logic; firstw : std_logic; fifo : fifo_type;end record;type pci_sync_regs is array (0 to NO_PCI_REGS - 1) of std_logic_vector(csync downto 0);type pci_reg_type is record pci : pci_sigs_type; noe_par : std_logic; noe_ad : std_logic; noe_ctrl : std_logic; noe_cbe : std_logic; noe_frame : std_logic; noe_irdy : std_logic; noe_req : std_logic; noe_perr : std_logic; m : pci_master_type; t : pci_target_type; comm : pci_config_command_type; -- Command register stat : pci_config_status_type; -- Status register bar0 : std_logic_vector(31 downto MADDR_WIDTH); -- Base Address register 0 bar1 : std_logic_vector(31 downto DMAMADDR_WIDTH); -- Base Address register 1 bar0_conf : std_logic; bar1_conf : std_logic; page : std_logic_vector(31 downto MADDR_WIDTH-1); -- AHB page ltim : std_logic_vector(7 downto 0); -- Latency timer cline : std_logic_vector(7 downto 0); -- Cache Line Size intline : std_logic_vector(7 downto 0); -- Interrupt Line syncs : pci_sync_regs; trans : std_logic_vector(NO_CPU_REGS - 1 downto 0);end record;type cpu_master_state_type is (idle, write, read_w, read, stop);type cpu_slave_state_type is (idle, w_wait, t_data, r_hold, r_wait, w_done, t_done);type cpu_master_type is record state : cpu_master_state_type; -- AMBA master state machine dmaddr : std_logic_vector(31 downto 0); fifo : fifo_type;end record;type cpu_slave_type is record state : cpu_slave_state_type; -- AMBA slave state machine maddr : std_logic_vector(31 downto 0); mdata : std_logic_vector(31 downto 0); be : std_logic_vector(3 downto 0); perror : std_logic; hresp : std_logic_vector(1 downto 0); hready : std_logic; htrans : std_logic_vector(1 downto 0); pcicomm : std_logic_vector(3 downto 0); hold : std_logic; fifos_write : std_logic; fifo : fifo_type;end record;type cpu_sync_regs is array (0 to NO_CPU_REGS - 1) of std_logic_vector(csync downto 0);type cpu_reg_type is record m : cpu_master_type; s : cpu_slave_type; syncs : cpu_sync_regs; trans : std_logic_vector(NO_PCI_REGS - 1 downto 0); pciba : std_logic_vector(3 downto 0); cfto : std_logic; wcomm : std_logic; rcomm : std_logic; werr : std_logic; clscnt : std_logic_vector(8 downto 0); dmapage : std_logic_vector(31 downto DMAMADDR_WIDTH); -- DMA page ioba : std_logic_vector(15 downto 0);end record;signal clk_int : std_logic;signal pr : pci_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 fifo1i, fifo2i, fifo3i, fifo4i : pci_fifo_in_type;signal fifo1o, fifo2o, fifo3o, fifo4o : pci_fifo_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, ahbsi, fifo2o, fifo4o, apbi) variable vdmai : ahb_dma_in_type; variable v : cpu_reg_type; variable hready : std_logic; variable hresp, hsize : std_logic_vector(1 downto 0); variable p_done, wsdone, wmdone, rtdone, rmdone : std_logic; variable pstart, habort, hstart_ack : std_logic; variable hstart, pabort, pstart_ack, pcidc : std_logic; variable i : integer range 0 to NO_CPU_REGS; variable fifom_write, fifos_write : std_logic; variable prdata : std_logic_vector(31 downto 0); variable wmvalid, wsvalid, rmvalid, rsvalid, burst_read, hold : std_logic; variable fifors_limit, fifows_limit,fiform_limit, fifowm_limit, fifows_stop : std_logic; variable comp, request, s_read_side, m_read_side : std_logic; begin v := r2; vdmai.start := '0'; vdmai.size := r.t.lsize; vdmai.irq := '0'; vdmai.busy := '0'; vdmai.burst := '1'; vdmai.wdata := fifo2o.rdata(31 downto 0); vdmai.write := r.t.lwrite; rmvalid := '1'; wmvalid := '1'; request := '0'; hold := '0'; rsvalid := '1'; wsvalid := '1'; burst_read := '0'; hready := '1'; hresp := HRESP_OKAY; hsize := "10"; fifom_write := '0'; v.s.fifos_write := '0'; comp := '0'; prdata := (others => '0'); v.s.hold := '0'; s_read_side := not r.m.fifo.side; m_read_side := not r.t.fifo.side; -- Synch registers pstart := r2.trans(0); habort := r2.trans(1); hstart_ack := r2.trans(2);-- fifows_limit := r2.trans(3); wsdone := r2.trans(4); wmdone := r2.trans(5); for i in 0 to NO_CPU_REGS - 1 loop v.syncs(i)(csync) := r.trans(i); if csync /= 0 then v.syncs(i)(0) := r2.syncs(i)(csync); end if; end loop; hstart := r2.syncs(0)(0); pabort := r2.syncs(1)(0); pstart_ack := r2.syncs(2)(0); pcidc := r2.syncs(3)(0); rtdone := r2.syncs(4)(0); rmdone := r2.syncs(5)(0); p_done := pstart_ack or pabort; if r2.m.fifo.raddr = FIFO_FULL then fiform_limit := '1'; else fiform_limit := '0'; end if; if r2.m.fifo.waddr = FIFO_FULL then fifowm_limit := '1'; else fifowm_limit := '0'; end if; if r2.s.fifo.raddr = FIFO_FULL then fifors_limit := '1'; else fifors_limit := '0'; end if; if r2.s.fifo.waddr = FIFO_FULL then fifows_limit := '1'; else fifows_limit := '0'; end if; if r2.s.fifo.waddr(FIFO_DEPTH - 2 downto 1) = FIFO_FULL(FIFO_DEPTH - 2 downto 1) then fifows_stop := '1'; else fifows_stop := '0'; end if;---- *** APB Control & Status regs *** ---- if (apbi.psel(pindex) and apbi.penable) = '1' then case apbi.paddr(4 downto 2) is when "000" => if apbi.pwrite = '1' then v.pciba := apbi.pwdata(31 downto 28); v.werr := r2.werr and not apbi.pwdata(14); v.wcomm := apbi.pwdata(10) and r.comm.mwie; v.rcomm := apbi.pwdata(9); end if; prdata := r2.pciba & "00000" & r.ltim & r2.werr & not pr.host & r.comm.msen & r.comm.men & r2.wcomm & r2.rcomm & r2.cfto & r.cline; when "001" => prdata := r.bar0(31 downto MADDR_WIDTH) & addzero(MADDR_WIDTH-1 downto 0); when "010" => prdata := r.page(31 downto MADDR_WIDTH-1) & addzero(MADDR_WIDTH-2 downto 0); when "011" => prdata := r.bar1(31 downto DMAMADDR_WIDTH) & addzero(DMAMADDR_WIDTH-1 downto 0); when "100" => if apbi.pwrite = '1' then v.dmapage(31 downto DMAMADDR_WIDTH) := apbi.pwdata(31 downto DMAMADDR_WIDTH); end if; prdata := r2.dmapage(31 downto DMAMADDR_WIDTH) & addzero(DMAMADDR_WIDTH-1 downto 0); when "101" => if apbi.pwrite = '1' then v.ioba := apbi.pwdata(31 downto 16); end if; prdata := r2.ioba & addzero(15 downto 4) & hstart & hstart_ack & pstart & pstart_ack; when "110" => prdata(1) := r.comm.men; prdata(2) := r.comm.msen; prdata(4) := r.comm.mwie; prdata(6) := r.comm.per; prdata(24) := r.stat.dped; prdata(26) := '1'; prdata(27) := r.stat.sta; prdata(28) := r.stat.rta; prdata(29) := r.stat.rma; prdata(31) := r.stat.dpe; when others => end case; end if;---- *** AHB MASTER *** ---- -- Burst control if (r2.m.state = read or r2.m.state = read_w) then if r.t.lmult = '1' then comp := fifowm_limit and r2.m.fifo.side; elsif r.t.lburst = '1' then if r2.clscnt(8) = '1' then comp := '1'; else v.clscnt := r2.clscnt - (dmao.active and dmao.ready); end if; else comp := '1'; end if; else v.clscnt := '0' & (r.cline - '1'); -- set burst counter to cache line size end if; if (rtdone = '1' and (r2.m.fifo.raddr + '1') = r.t.fifo.waddr) then rmvalid := '0'; end if; --step DMA address if dmao.ready = '1' then v.m.dmaddr(31 downto 2) := r2.m.dmaddr(31 downto 2) + '1'; end if; -- AHB master state machine case r2.m.state is when idle => if hstart = '1' then wmdone := '0'; fifowm_limit := '0'; vdmai.start := '1'; v.m.fifo.waddr := (others => '0'); if dmao.active = '1' then
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?