1 ---------------------------------------------------------------------
3 -- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 -- DATE CREATED: 12/27/07
5 -- FILENAME: eth_dma.vhd
6 -- PROJECT: Plasma CPU core
7 -- COPYRIGHT: Software placed into the public domain by the author.
8 -- Software 'as is' without warranty. Author liable for nothing.
10 -- Ethernet DMA (Direct Memory Access) controller.
11 -- Reads four bits and writes four bits from/to the Ethernet PHY each
12 -- 2.5 MHz clock cycle. Received data is DMAed starting at 0x13ff0000
13 -- transmit data is read from 0x13fd0000.
14 -- To send a packet write bytes/4 to Ethernet send register.
15 ---------------------------------------------------------------------
17 use ieee.std_logic_1164.all;
18 use ieee.std_logic_unsigned.all;
19 use ieee.std_logic_arith.all;
20 use work.mlite_pack.all;
22 entity eth_dma is port(
23 clk : in std_logic; --25 MHz
25 enable_eth : in std_logic; --enable receive DMA
26 select_eth : in std_logic;
27 rec_isr : out std_logic; --data received
28 send_isr : out std_logic; --transmit done
30 address : out std_logic_vector(31 downto 2); --to DDR
31 byte_we : out std_logic_vector(3 downto 0);
32 data_write : out std_logic_vector(31 downto 0);
33 data_read : in std_logic_vector(31 downto 0);
34 pause_in : in std_logic;
36 mem_address : in std_logic_vector(31 downto 2); --from CPU
37 mem_byte_we : in std_logic_vector(3 downto 0);
38 data_w : in std_logic_vector(31 downto 0);
39 pause_out : out std_logic;
41 E_RX_CLK : in std_logic; --2.5 MHz receive
42 E_RX_DV : in std_logic; --data valid
43 E_RXD : in std_logic_vector(3 downto 0); --receive nibble
44 E_TX_CLK : in std_logic; --2.5 MHz transmit
45 E_TX_EN : out std_logic; --transmit enable
46 E_TXD : out std_logic_vector(3 downto 0)); --transmit nibble
49 architecture logic of eth_dma is
50 signal rec_clk : std_logic_vector(1 downto 0); --receive
51 signal rec_store : std_logic_vector(31 downto 0); --to DDR
52 signal rec_data : std_logic_vector(27 downto 0);
53 signal rec_cnt : std_logic_vector(2 downto 0); --nibbles
54 signal rec_words : std_logic_vector(13 downto 0);
55 signal rec_dma : std_logic_vector(1 downto 0); --active & request
56 signal rec_done : std_logic;
58 signal send_clk : std_logic_vector(1 downto 0); --transmit
59 signal send_read : std_logic_vector(31 downto 0); --from DDR
60 signal send_data : std_logic_vector(31 downto 0);
61 signal send_cnt : std_logic_vector(2 downto 0); --nibbles
62 signal send_words : std_logic_vector(8 downto 0);
63 signal send_level : std_logic_vector(8 downto 0);
64 signal send_dma : std_logic_vector(1 downto 0); --active & request
65 signal send_enable: std_logic;
69 dma_proc: process(clk, reset, enable_eth, select_eth,
70 data_read, pause_in, mem_address, mem_byte_we, data_w,
71 E_RX_CLK, E_RX_DV, E_RXD, E_TX_CLK,
72 rec_clk, rec_store, rec_data,
73 rec_cnt, rec_words, rec_dma, rec_done,
74 send_clk, send_read, send_data, send_cnt, send_words,
75 send_level, send_dma, send_enable)
81 rec_words <= ZERO(13 downto 0);
86 send_words <= ZERO(8 downto 0);
87 send_level <= ZERO(8 downto 0);
90 elsif rising_edge(clk) then
92 --Receive nibble on low->high E_RX_CLK. Send to DDR every 32 bits.
93 rec_clk <= rec_clk(0) & E_RX_CLK;
94 if rec_clk = "01" and enable_eth = '1' then
95 if E_RX_DV = '1' or rec_cnt /= "000" then
96 if rec_cnt = "111" then
97 rec_store <= rec_data & E_RXD;
98 rec_dma(0) <= '1'; --request DMA
100 rec_data <= rec_data(23 downto 0) & E_RXD;
101 rec_cnt <= rec_cnt + 1;
105 --Set transmit count or clear receive interrupt
106 if select_eth = '1' then
107 if mem_byte_we /= "0000" then
109 send_words <= ZERO(8 downto 0);
110 send_level <= data_w(8 downto 0);
117 --Transmit nibble on low->high E_TX_CLK. Get 32 bits from DDR.
118 send_clk <= send_clk(0) & E_TX_CLK;
119 if send_clk = "01" then
120 if send_cnt = "111" then
121 if send_words /= send_level then
122 send_data <= send_read;
129 send_data(31 downto 4) <= send_data(27 downto 0);
131 send_cnt <= send_cnt + 1;
134 --Pick which type of DMA operation: bit0 = request; bit1 = active
135 if pause_in = '0' then
136 if rec_dma(1) = '1' then
137 rec_dma <= "00"; --DMA done
138 rec_words <= rec_words + 1;
139 if E_RX_DV = '0' then
142 elsif send_dma(1) = '1' then
144 send_words <= send_words + 1;
145 send_read <= data_read;
146 elsif rec_dma(0) = '1' then
147 rec_dma(1) <= '1'; --start DMA
148 elsif send_dma(0) = '1' then
149 send_dma(1) <= '1'; --start DMA
153 end if; --rising_edge(clk)
155 E_TXD <= send_data(31 downto 28);
156 E_TX_EN <= send_enable;
158 if send_words = send_level then
164 if rec_dma(1) = '1' then
165 address <= "0001001111111111" & rec_words; --0x13ff0000
167 data_write <= rec_store;
168 pause_out <= '1'; --to CPU
169 elsif send_dma(1) = '1' then
170 address <= "000100111111111000000" & send_words; --0x13fe0000
172 data_write <= data_w;
175 address <= mem_address; --Send request from CPU to DDR
176 byte_we <= mem_byte_we;
177 data_write <= data_w;
183 end; --architecture logic