📄 dmacntrl.vhd
字号:
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 + -