You are on page 1of 7

DMA controller

library ieee;
library work;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use work.components.all;

entity dma is

Port (
clk : in std_logic; -- clock
rstn : in std_logic; -- reset
start : in std_logic; -- trigger state machine
dati : in std_logic_vector(31 downto 0); -- data input
adr : in std_logic_vector(7 downto 0); &nbsp-- address of the dma
register
reg_wen : in std_logic; -- dma register write enable
fifo_wen : in std_logic; -- dma fifo write enable
wr_rdn : in std_logic; -- write/read signal to dma registers
cs : in std_logic; -- chip select (dma_register)
bcr_cnten : in std_logic; -- byte counter count enable
acr_cnten : in std_logic; -- address counter count enable
lar_cnten : in std_logic; -- local address counter count
enable
p2s_fifo_empty : in std_logic; -- high and low p2s both empty
s2p_fifo_usedw : in std_logic_vector(6 downto 0);
mstr_busy : in std_logic;
stop : in std_logic; -- PCI core signals stop current dma
abort : in std_logic; -- PCI core signals abort current dma
last_xfr : in std_logic; -- PCI core signals last transfer
local_busy : in std_logic; -- sdram is busy
err_pend : in std_logic; -- target abort, parity error, master
abort
lm_tsr : in std_logic_vector(9 downto 0); &nbsp-- master status
std_logics
isr_rd : in std_logic; -- isr read signal

isr : out std_logic_vector(5 downto 0);


csr : out std_logic_vector(8 downto 0);
bcr : out std_logic_vector(16 downto 0);
acr : out std_logic_vector(31 downto 0);
lar : out std_logic_vector(25 downto 0);
req : out std_logic; -- dma requesting a PCI core for data
transfer
local_start : out std_logic; -- dma requesting sdram controller
to start data transfer
dato : out std_logic_vector(31 downto 0); &nbsp-- dma register read
data output
probe : out std_logic_vector(7 downto 0)
);

end dma;

architecture rtl of dma is

signal normal_termination : std_logic;


signal start_chain : std_logic;
signal chain_end : std_logic;
signal dma_bcr : std_logic_vector(16 downto 0);
signal dma_csr : std_logic_vector(8 downto 0);
signal dma_done : std_logic;
signal dma_error : std_logic;
signal chain_acr_ld : std_logic;
signal chain_bcr_ld : std_logic;
signal dma_fifo_rd : std_logic;
signal trans64 : std_logic;
signal isr_in : std_logic_vector(5 downto 0);
signal dma_on : std_logic;
signal dma_acr : std_logic_vector(31 downto 0);
signal dma_isr : std_logic_vector(5 downto 0);
signal dma_lar : std_logic_vector(25 downto 0);
signal dma_fifo_dato : std_logic_vector(31 downto 0);
signal soft_flush : std_logic;
signal dma_reg_dati : std_logic_vector(31 downto 0);
signal reg_dat_sel : std_logic;
signal direction : std_logic;
signal acr_wr : std_logic;
signal csr_wr : std_logic;
signal csr_wr_reg : std_logic;
signal int_irq : std_logic;
signal local_irq : std_logic;
signal rst : std_logic;
signal req_int : std_logic;
signal high : std_logic;
signal dma_reg_hit : std_logic_vector(4 downto 0);
begin
&nbsphigh <= '1';
&nbsprst <= not rstn;
&nbspsoft_flush <= dma_csr(1); &nbsp-- flush std_logic of the control status
register
&nbspstart_chain <= dma_isr(5); &nbsp-- DMA chaining mode enable
&nbspdirection <= dma_csr(3); &nbsp-- 1 for write, 0 for read

-- interrupt pending std_logic


&nbspisr_in(0) <= err_pend or int_irq or (dma_isr(3) and not dma_csr(5));
&nbspint_irq <= local_irq;

-- assert local irq when there is error pending or DMA has completed
&nbsplocal_irq <= dma_isr(1) or (dma_isr(3) and not dma_csr(5));
&nbspisr_in(1) <= err_pend;

&nbspisr_in(2) <= int_irq;

-- generate transfer complete status std_logic 3

&nbspprocess(dma_done, isr_rd, csr_wr, acr_wr, dma_isr) -- dma_tc


begin
&nbspif(dma_done = '1') then
isr_in(3) <= '1';
&nbspelsif(isr_rd = '1' or csr_wr = '1' or acr_wr = '1') then
isr_in(3) <= '0';
&nbspelse
isr_in(3) <= dma_isr(3);
&nbspend if;
end process;

-- write signal to the address counter


&nbspacr_wr <= dma_reg_hit(1) and cs and reg_wen;

-- generate ad_loaded singal for the isr std_logic 4


&nbspprocess(acr_wr, dma_isr, soft_flush, dma_done, dma_error)
begin
&nbspif(acr_wr = '1') then
isr_in(4) <= '1';
&nbspelsif(dma_isr(3) = '1' or soft_flush = '1' or dma_done = '1' or dma_error =
'1') then
isr_in(4) <= '0';
&nbspelse
isr_in(4) <= dma_isr(4);
&nbspend if;
end process;

-- control status register write signal


&nbspcsr_wr <= dma_reg_hit(0) and cs and reg_wen;

&nbspprocess(clk,rstn) &nbsp-- register csr_wr


begin
&nbspif(rstn='0') then
csr_wr_reg <= '0';
&nbspelsif(clk'event and clk = '1') then
csr_wr_reg <= csr_wr;
&nbspend if;
end process;

-- generate start_chain std_logic


&nbspprocess(csr_wr_reg, dma_isr, dma_csr, soft_flush, dma_done, dma_error)
begin
&nbspif (csr_wr_reg = '1' and dma_csr(8) = '1') then &nbsp-- start
chain
isr_in(5) <= '1';
&nbspelsif (dma_isr(3) = '1' or soft_flush = '1' or dma_done = '1' or dma_error
='1') then
isr_in(5) <= '0';
&nbspelse
isr_in(5) <= dma_isr(5);
&nbspend if;
end process;

-- generate dma_on std_logic csr(6)

&nbspdma_on <= (dma_isr(4) and dma_csr(4) and not err_pend) or (isr_in(5) and
dma_csr(4) and &nbspnot err_pend);

-- dma state machine instantiation


dma_sm0 : dma_sm

port map (
clk => &nbspclk,
rstn => &nbsprstn,
normal_termination => &nbspnormal_termination,
stop => &nbspstop,
lm_tsr => &nbsplm_tsr,
err_pend => &nbsperr_pend,
start => &nbspstart ,
start_chain => &nbspstart_chain,
chain_end => &nbspchain_end,
p2s_fifo_empty => &nbspp2s_fifo_empty,
s2p_fifo_usedw => &nbsps2p_fifo_usedw,
direction => &nbspdirection,
dma_bcr => &nbspdma_bcr,
local_busy => &nbsplocal_busy,
req => &nbspreq_int,
dma_done => &nbspdma_done,
dma_error => &nbspdma_error,
chain_acr_ld => &nbspchain_acr_ld,
chain_bcr_ld => &nbspchain_bcr_ld,
dma_fifo_rd => &nbspdma_fifo_rd,
local_start => &nbsplocal_start,
chain_dma_loading => &nbspreg_dat_sel

);

-- DMA registers instantiation


&nbspdma_reg0 : dma_reg

&nbspport map (
clk => &nbspclk ,
rstn => &nbsprstn ,
adr => &nbspadr ,
dati => &nbspdma_reg_dati , -- mux output select between
dati and dma_fifo_dato
wen => &nbspreg_wen ,
acr_ld => &nbspchain_acr_ld ,
bcr_ld => &nbspchain_bcr_ld ,
acr_cnten => &nbspacr_cnten,
lar_cnten => &nbsplar_cnten,
bcr_cnten => &nbspbcr_cnten,
isr_in => &nbspisr_in ,
dma_on => &nbspdma_on ,
cs => &nbspcs,
acr => &nbspdma_acr ,
bcr => &nbspdma_bcr ,
csr => &nbspdma_csr ,
isr => &nbspdma_isr ,
lar => &nbspdma_lar ,
dato => &nbspdato,
dma_reg_hit => &nbspdma_reg_hit
);

&nbsp-- muxing data input to dma register


-- data comes from the pci side or the descriptor
process(reg_dat_sel, dati, dma_fifo_dato)
begin
case (reg_dat_sel) is
when '1' =>
dma_reg_dati <= dma_fifo_dato; &nbsp-- descriptor fifo for chaining DMA
when OTHERS =>
dma_reg_dati <= dati;
end case;
end process;

-- set normal termination when lm_lastn has asserted

req <= req_int;


process(clk,rstn)
begin
if(rstn='0') then
normal_termination <= '0';
elsif(clk'event and clk='1') then
if(last_xfr='1') then
normal_termination <= '1'; &nbsp-- set when lm_last
elsif(req_int='1') then
normal_termination <= '0'; &nbsp-- reset when request
end if;
end if;
end process;

-- assign outputs

bcr <= dma_bcr;


acr <= dma_acr;
lar <= dma_lar;
csr <= dma_csr;
isr <= dma_isr;

end rtl;

You might also like