⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dmacntrl.vhd

📁 VHDLVERILOG语言实现的CARDBUS的IP源码,已经实现现场应用
💻 VHD
📖 第 1 页 / 共 2 页
字号:
        WrRdAdr  <= '0';
        WrWrAdr  <= '0';
        WrDMACnt <= '0';
		WrDReg   <= '0';
        if Usr_Write = '1' and IncrAddr = '1' then
            case Usr_Ad is 
                when "01000011" => WrCtrl   <= '1'; -- address 0x10C    
                when "01000010" => WrRdAdr  <= '1'; -- address 0x108
                when "01000001" => WrWrAdr  <= '1'; -- address 0x104
                when "01000000" => WrDMACnt <= '1'; -- address 0x100
                when "01000111" => WrDReg   <= '1'; -- address 0x11C
                when others => null;
            end case;
        end if;
    end process;

	-- BE FIFO write addressing, mapped to address range 0x200 to 0x2FC
	BEfifo <= '1' when Usr_Write = '1' and IncrAddr = '1' and Usr_Ad(9 downto 8) = "10" else '0';

	-- Master data register so that data don't have to always come from/go to FIFO
	process (PCI_clk, PCI_reset)
	begin
		if PCI_reset = '1' then Mst_D_Reg <= x"00000000";
        elsif PCI_clk'event and PCI_clk = '1' then
		    if ((Mst_RdData_Valid = '1' and Mst_RdData_Sel = '1') or WrDReg = '1') then
			    Mst_D_Reg <= Usr_WrData;
			end if;
		end if;
	end process;

	WD_Reg <= Mst_D_Reg;

    -- Instantiate address incrementers
    IncRdAdr   <= Mst_RdData_Valid;
    IncWrAdr   <= Mst_Xfer_D1 and Mst_WrMode;
    LdRdAdrCnt <= WrRdAdr and not Usr_CBE(0) and not Usr_CBE(1) and
                   not Usr_CBE(2) and not Usr_CBE(3);
    LdWrAdrCnt <= WrWrAdr and not Usr_CBE(0) and not Usr_CBE(1) and 
                   not Usr_CBE(2) and not Usr_CBE(3);

    RdAdrReg: ucount30 port map (CLR=>PCI_reset, CLK=>PCI_clk, EN=>IncRdAdr, 
              LOAD=>LdRdAdrCnt, D=>Usr_WrData(29 downto 0), Q=>Mst_RdAd(31 downto 2));
    
    WrAdrReg: ucount30 port map (CLR=>PCI_reset, CLK=>PCI_clk, EN=>IncWrAdr,
              LOAD=>LdWrAdrCnt, D=>Usr_WrData(29 downto 0), Q=>Mst_WrAd(31 downto 2));

    Mst_RdAd(1 downto 0) <= "00";
    Mst_WrAd(1 downto 0) <= "00";

    -- Instantiate Down Counters for DMA Read and Write Count
    LdWrCnt     <= WrDMACnt and not Usr_CBE(0) and not Usr_CBE(1);
    LdRdCnt     <= WrDMACnt and not Usr_CBE(2) and not Usr_CBE(3);
    DecDMARdCnt <= IncRdAdr;

    process (PCI_clk)
    begin
        if PCI_clk'event and PCI_clk = '1' then
            DecDMAWrCnt <= Mst_WrData_Rdy and Mst_WrMode;
        end if;
    end Process;
    
    RdCntReg: dcount16 port map (CLR=>PCI_reset, CLK=>PCI_clk, EN=>DecDMARdCnt,
              LOAD=>LdRdCnt, D=>Usr_WrData(31 downto 16), Q=>DMARdCnt(15 downto 0));

    WrCntReg: dcount16 port map (CLR=>PCI_reset, CLK=>PCI_clk, EN=>DecDMAWrCnt,
              LOAD=>LdWrCnt, D=>Usr_WrData(15 downto  0), Q=>DMAWrCnt(15 downto 0));

    DMACntReg <= DMARdCnt & DMAWrCnt;

    -- DMA Control Status Register Write
    process (PCI_clk, PCI_reset)
    begin
        if (PCI_reset = '1') then
            DMAWrEn_local <= '0';
            DMARdEn_local <= '0';
            DMAWrErr      <= '0';
            DMARdErr      <= '0';
            LocalEn_local <= '0';
            Mst_LatCntEn_local <= '0';
            Mst_RdCmd     <= "0001";  -- 01 = Memory Read
			Mst_WrCmd     <= "011";
			Mst_RdBE_Sel  <= '0';
			Mst_RdBE      <= "0000";
			Mst_WrBE      <= "0000";
			Mst_WrBE_Sel  <= '0';
			Mst_Rd_Term_Sel_local <= '0';
			Mst_RdData_Sel <= '0';
			Mst_WrData_Sel <= '0';
        elsif PCI_clk'event and PCI_clk = '1' then
            if WrCtrl = '1' and Usr_CBE(3) = '0' then
                Mst_LatCntEn_local <= Usr_WrData(31);
                LocalEn_local      <= Usr_WrData(30);
                Mst_RdCmd          <= Usr_WrData(29 downto 26);
                DMARdErr           <= Usr_WrData(25);
                DMARdEn_local      <= Usr_WrData(24);
            end if;
			if WrCtrl = '1' and Usr_CBE(2) = '0' then
				Mst_Rd_Term_Sel_local <= Usr_WrData(23);
				Mst_RdBE_Sel       <= Usr_WrData(22);
				Mst_RdBE           <= Usr_WrData(21 downto 18);
				Mst_WrBE(3 downto 2) <= Usr_WrData(17 downto 16);
			end if;
			if WrCtrl = '1' and Usr_CBE(1) = '0' then
				Mst_WrBE(1 downto 0) <= Usr_WrData(15 downto 14);
				Mst_WrBE_Sel       <= Usr_WrData(13);
				Mst_WrCmd          <= Usr_WrData(12 downto 10);
                DMAWrErr           <= Usr_WrData(9);
                DMAWrEn_local      <= Usr_WrData(8);
            end if;
			if WrCtrl = '1' and Usr_CBE(0) = '0' then
				Mst_RdData_Sel     <= Usr_WrData(7);
				Mst_WrData_Sel     <= Usr_WrData(6);
			end if;
            if (Mst_Tabort_Det = '1' or Mst_TTO_Det = '1') and Mst_RdMode = '1' then
                DMARdEn_local  <= '0';
                DMARdErr <= '1';
            end if;
            if RdCnt0 = '1' and DMARdEn_local = '1' then
                DMARdEn_local  <= '0';
            end if;
            if (Mst_Tabort_Det = '1' or Mst_TTO_Det = '1') and Mst_WrMode = '1' then
                DMAWrEn_local  <= '0';
                DMAWrErr <= '1';
            end if;
            if WrCnt0 = '1' and DMAWrEn_local = '1' and Mst_WrBurst_Done = '1' then
                DMAWrEn_local <= '0';
            end if;
        end if;
    end process;

    DMACtrlStat <= Mst_LatCntEn_local & LocalEn_local & Mst_RdCmd(3 downto 0) & DMARdErr & DMARdEn_local
                 & Mst_Rd_Term_Sel_local & Mst_RdBE_Sel & Mst_RdBE(3 downto 0) & Mst_WrBE(3 downto 2)
                 & Mst_WrBE(1 downto 0) & Mst_WrBE_Sel & Mst_WrCmd(2 downto 0) & DMAWrErr & DMAWrEn_local
                 & "00000000";

    -- Create read/write enable control for state machine
    PCIWrEn <= DMAWrEn_local and BusMstEn;
    PCIRdEn <= DMARdEn_local and BusMstEn;

    -- Current Burst Count Decodes
    BCnt_eq_3 <= '1' when (Burst_Cnt = "00000011") else '0';
    BCnt_eq_2 <= '1' when (Burst_Cnt = "00000010") else '0';
    BCnt_eq_1 <= '1' when (Burst_Cnt = "00000001") else '0';
    BCnt2_eq_1 <= '1' when (Burst_Cnt2 = "00000001") else '0';

    -- Check for end of DMA
    RdBCnt <= Burst_Length when (DMARdCnt > Burst_Length) else DMARdCnt(7 downto 0);
    WrBCnt <= Burst_Length when (DMAWrCnt > Burst_Length) else DMAWrCnt(7 downto 0);
            
    process (PCI_clk)
    begin
        if PCI_clk'event and PCI_clk = '1' then
            RdCnt0 <= '0';
            WrCnt0 <= '0';
            if RdBCnt = "00000000" then RdCnt0 <= '1';  end if;
            if WrBCnt = "00000000" then WrCnt0 <= '1';  end if;
        end if;
    end process;
                                                 
    -- DMA State Machine
    process (PCI_clk, PCI_reset)
    begin
    	if PCI_reset = '1' then
	        DMASm         <= idle;
	        Mst_Burst_Req    <= '0';
	        Mst_WrData_Valid <= '0';
			Mst_RdBE_Load_Done <= '0';
		elsif PCI_clk'event and PCI_clk = '1' then

	        if DMASm(idle_bt) = '1' then
	        	-- Back end ready, software enabled, and >0 transfers remain
	            if PCIWrEn = '1' and WrCnt0 = '0' and (WrRdy = '1' or Mst_WrData_Sel = '1') then 
	                DMASm <= dma_wr;
	            elsif PCIRdEn = '1' and RdCnt0 = '0' and (RdRdy ='1' or Mst_RdData_Sel = '1') then
	                DMASm <= dma_rd;
	            else DMASm <= idle;
	            end if;
	        end if;

	        if DMASm(dma_rd_bt) = '1' then  
	        	-- if 1 left, and we are in the last transfer cycle
	        	-- go to read wait state to wait for last transfer
	            if Mst_RdBurst_Done = '1' or DMARdErr = '1' then
	                DMASm <= dma_rd_wt;  -- go to tx wait state to wait for last transfer
	                Mst_Burst_Req <= '0';
					Mst_RdBE_Load_Done <= '0';
	            else
	                DMASm <= dma_rd;
	                Mst_Burst_Req <= '1';
	            end if;

				-- if in multi-BE mode master read
				if Mst_RdBE_Sel = '1' and Mst_RdBE_Load_Done = '0' then
					if BCnt2_eq_1 = '1' and Mst_WrData_Rdy = '1' then
						-- all BEs are transferred to PCI core
						-- set flag to remember "done"
						Mst_WrData_Valid <= '0';
						Mst_RdBE_Load_Done <= '1';
					else
						-- still more BEs left
						Mst_WrData_Valid <= '1';
						Mst_RdBE_Load_Done <= '0';
					end	if;
				end if;
	        end if;

	        if DMASm(dma_rd_wt_bt) = '1' then
	            DMASm <= idle;
	        end if;

	        if DMASm(dma_wr_bt) = '1' then
	            Mst_Burst_Req <= '1';
	            Mst_WrData_Valid <= '1';
	            if (BCnt_eq_1 = '1' or LastWr = '1') and Mst_WrData_Rdy = '1' then
	            	DMASm <= dma_wr_wt;
					Mst_WrData_Valid <= '0';
	            elsif DMAWrErr = '1' then DMASm <= idle;
	            else DMASm <= dma_wr;
	            end if;
	        end if;

	        if DMASm(dma_wr_wt_bt) = '1' then
	            -- if no error and pipeline is not empty
	            --  stay in this state, otherwise go to idle
	            if DMAWrErr = '0' and Mst_WrBurst_Done = '0' then
	                DMASm <= dma_wr_wt;
	                Mst_Burst_Req <= '1';
	            else
	                DMASm <= idle;
	                Mst_Burst_Req <= '0';
	            end if;
	        end if;
		end if;
    end process;

    -- DMA Burst Counter
    Init_BCnt <= WrBCnt when DMASm(dma_wr_bt) = '1' and WrRdy = '1' and PCIWrEn = '1' and WrCnt0 = '0' else RdBCnt;
    Ld_BCnt   <= DMASm(idle_bt);
    Dec_BCnt  <= (DMASm(dma_rd_bt) and Mst_Xfer_D1) or (Mst_WrData_Rdy and Mst_WrMode);
    Dec_BCnt2  <= DMASm(dma_rd_bt) and Mst_WrData_Rdy and Mst_RdBE_Sel;

    BRSTCNTR: dcount8 port map (CLK=>PCI_clk, CLR=>PCI_reset, D=>Init_BCnt,
                             EN=>Dec_BCnt, LOAD=>Ld_BCnt, Q=>Burst_Cnt);

    BRSTCNTR2: dcount8 port map (CLK=>PCI_clk, CLR=>PCI_reset, D=>Init_BCnt,
                             EN=>Dec_BCnt2, LOAD=>Ld_BCnt, Q=>Burst_Cnt2);

    -- DMA Burst State Machine Outputs
    Mst_One_Read     <= BCnt_eq_1 or (BCnt_eq_2 and Mst_Xfer_D1);
    Mst_Two_Reads    <= DMARdErr or (BCnt_eq_2 or (BCnt_eq_3 and Mst_Xfer_D1));
    Mst_RdMode <= DMASm(dma_rd_bt) or DMASm(dma_rd_wt_bt);
    Mst_WrMode <= DMASm(dma_wr_bt) or DMASm(dma_wr_wt_bt);

end behavioral;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -