]> rtime.felk.cvut.cz Git - fpga/plasma.git/blob - vhdl/eth_dma.vhd
Local copy of Plasma MIPS project.
[fpga/plasma.git] / vhdl / eth_dma.vhd
1 ---------------------------------------------------------------------
2 -- TITLE: Ethernet DMA
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.
9 -- DESCRIPTION:
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 ---------------------------------------------------------------------
16 library ieee;
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;
21
22 entity eth_dma is port(
23    clk         : in std_logic;                      --25 MHz
24    reset       : in std_logic;
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
29
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;
35
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;
40
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
47 end; --entity eth_dma
48
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;
57
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;
66
67 begin  --architecture
68
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)
76    begin
77
78       if reset = '1' then
79          rec_clk <= "00";
80          rec_cnt <= "000";
81          rec_words <= ZERO(13 downto 0);
82          rec_dma <= "00";
83          rec_done <= '0';
84          send_clk <= "00";
85          send_cnt <= "000";
86          send_words <= ZERO(8 downto 0);
87          send_level <= ZERO(8 downto 0);
88          send_dma <= "00";
89          send_enable <= '0';
90       elsif rising_edge(clk) then
91
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
99                end if;
100                rec_data <= rec_data(23 downto 0) & E_RXD;
101                rec_cnt <= rec_cnt + 1;
102             end if;
103          end if;
104
105          --Set transmit count or clear receive interrupt
106          if select_eth = '1' then
107             if mem_byte_we /= "0000" then
108                send_cnt <= "000";
109                send_words <= ZERO(8 downto 0);
110                send_level <= data_w(8 downto 0);
111                send_dma(0) <= '1';
112             else
113                rec_done <= '0';
114             end if;
115          end if;
116
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;
123                   send_dma(0) <= '1';
124                   send_enable <= '1';
125                else
126                   send_enable <= '0';
127                end if;
128             else
129                send_data(31 downto 4) <= send_data(27 downto 0);
130             end if;
131             send_cnt <= send_cnt + 1;
132          end if;
133
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
140                   rec_done <= '1';
141                end if;
142             elsif send_dma(1) = '1' then
143                send_dma <= "00";
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
150             end if;
151          end if;
152
153       end if;  --rising_edge(clk)
154
155       E_TXD <= send_data(31 downto 28);
156       E_TX_EN <= send_enable;
157       rec_isr <= rec_done;
158       if send_words = send_level then
159          send_isr <= '1';
160       else
161          send_isr <= '0';
162       end if;
163
164       if rec_dma(1) = '1' then
165          address <= "0001001111111111" & rec_words;        --0x13ff0000
166          byte_we <= "1111";
167          data_write <= rec_store;
168          pause_out <= '1';                                 --to CPU
169       elsif send_dma(1) = '1' then
170          address <= "000100111111111000000" & send_words;  --0x13fe0000
171          byte_we <= "0000";
172          data_write <= data_w;
173          pause_out <= '1';
174       else
175          address <= mem_address;  --Send request from CPU to DDR
176          byte_we <= mem_byte_we;
177          data_write <= data_w;
178          pause_out <= '0';
179       end if;
180
181    end process;
182
183 end; --architecture logic