1 |
30 |
dgisselq |
////////////////////////////////////////////////////////////////////////////////
|
2 |
|
|
//
|
3 |
|
|
// Filename: enetpackets.v
|
4 |
|
|
//
|
5 |
|
|
// Project: OpenArty, an entirely open SoC based upon the Arty platform
|
6 |
|
|
//
|
7 |
|
|
// Purpose: To communicate between the Ethernet PHY, and thus to coordinate
|
8 |
|
|
// (and direct/arrange for) the transmission, and receiption, of
|
9 |
|
|
// packets via the Ethernet interface.
|
10 |
|
|
//
|
11 |
|
|
//
|
12 |
|
|
// Using this interface requires four registers to be properly configured.
|
13 |
|
|
// These are the receive and transmit control registers, as well as the
|
14 |
|
|
// hardware MAC register(s).
|
15 |
|
|
//
|
16 |
|
|
//
|
17 |
|
|
// To use the interface, after the system has been alive for a full
|
18 |
|
|
// second, drop the reset line. Do this by writing to the transmit
|
19 |
|
|
// register a value with zero length, zero command, and the RESET bit as
|
20 |
|
|
// zero.
|
21 |
|
|
//
|
22 |
|
|
// This interface is big endian. Therefore, the most significant byte
|
23 |
|
|
// in each word will be transmitted first. If the interface references
|
24 |
|
|
// a number of octets less than a multiple of four, the least significant
|
25 |
|
|
// octets in the last word will not be transmitted/were not received.
|
26 |
|
|
//
|
27 |
|
|
// To transmit,
|
28 |
|
|
// 1. set the source MAC address in the two mac registers. These
|
29 |
|
|
// are persistent across packets, so once set (whether for
|
30 |
|
|
// transmit or receive) they need not be set again.
|
31 |
|
|
// 2. Fill the packet buffer with your packet. In general, the
|
32 |
|
|
// first 32-bit word must contain the hardware MAC address
|
33 |
|
|
// of your destination, spilling into the 16-bits of the
|
34 |
|
|
// next word. The bottom 16-bits of that second word
|
35 |
|
|
// must also contain the EtherType (0x0800 for IP,
|
36 |
|
|
// 0x0806 for ARP, etc.) The third word will begin your
|
37 |
|
|
// user data.
|
38 |
|
|
// 3. Write a 0x4000 plus the number of bytes in your buffer to
|
39 |
|
|
// the transmit command register. If your packet is less
|
40 |
|
|
// than 64 bytes, it will automatically be paddedd to 64
|
41 |
|
|
// bytes before being sent.
|
42 |
|
|
// 4. Once complete, the controller will raise an interrupt
|
43 |
|
|
// line to note that the interface is idle.
|
44 |
|
|
// OPTIONS:
|
45 |
|
|
// You can turn off the internal insertion of the hardware source
|
46 |
|
|
// MAC by turning the respective bit on in the transmit command
|
47 |
|
|
// register. If you do this, half of the second word and all the
|
48 |
|
|
// third word must contain the hardware MAC. The third word must
|
49 |
|
|
// contain the EtherType, both in the top and bottom sixteen bits.
|
50 |
|
|
// The Fourth word will begin user data.
|
51 |
|
|
//
|
52 |
|
|
// You can also turn off the automatic insertion of the FCS, or
|
53 |
|
|
// ethernet CRC. Doing this means that you will need to both
|
54 |
|
|
// guarantee for yourself that the packet has a minimum of 64
|
55 |
|
|
// bytes in length, and that the last four bytes contain the
|
56 |
|
|
// CRC.
|
57 |
|
|
//
|
58 |
|
|
// To Receive:
|
59 |
|
|
// The receiver is always on. Receiving is really just a matter
|
60 |
|
|
// of pulling the received packet from the interface, and resetting
|
61 |
|
|
// the interface for the next packet.
|
62 |
|
|
//
|
63 |
|
|
// If the VALID bit is set, the receive interface has a valid
|
64 |
|
|
// packet within it. Write a zero to this bit to reset the
|
65 |
|
|
// interface to accept the next packet.
|
66 |
|
|
//
|
67 |
|
|
// If a packet with a CRC error is received, the CRC error bit
|
68 |
|
|
// will be set. Likewise if a packet has been missed, usually
|
69 |
|
|
// because the buffer was full when it started, the miss bit
|
70 |
|
|
// will be set. Finally, if an error occurrs while receiving
|
71 |
|
|
// a packet, the error bit will be set. These bits may be cleared
|
72 |
|
|
// by writing a one to each of them--something that may be done
|
73 |
|
|
// when clearing the interface for the next packet.
|
74 |
|
|
// OPTIONS:
|
75 |
|
|
// The same options that apply to the transmitter apply to the
|
76 |
|
|
// receiver:
|
77 |
|
|
//
|
78 |
|
|
// HWMAC. If the hardware MAC is turned on, the receiver will
|
79 |
|
|
// only accept packets to either 1) our network address, or 2)
|
80 |
|
|
// a broadcast address. Further, the first two words will be
|
81 |
|
|
// adjusted to contain the source MAC and the EtherType, so that
|
82 |
|
|
// the user information begins on the third word. If this feature
|
83 |
|
|
// is turned off, all packets will be received, and the first
|
84 |
|
|
// three words will contain the destination and then source
|
85 |
|
|
// MAC. The fourth word will contain the EtherType in the lowest,
|
86 |
|
|
// 16 bits, meaning user data will begin on the fifth word.
|
87 |
|
|
//
|
88 |
|
|
// HWCRC. If the HWCRC is turned on, the receiver will only
|
89 |
|
|
// detect packets that pass their CRC check. Further, the packet
|
90 |
|
|
// length (always in octets) will not include the CRC. However,
|
91 |
|
|
// the CRC will still be left/written to packet memory either way.
|
92 |
|
|
//
|
93 |
|
|
// Registers:
|
94 |
|
|
// 0 Receiver control
|
95 |
|
|
// 13'h0 |CRCerr|MISS|ERR|BUSY|VALID |14-bit length (in octets)|
|
96 |
|
|
//
|
97 |
|
|
// 1 Transmitter control
|
98 |
|
|
// 14'h0 |NET_RST|SW-MAC-CHK|SW-CRCn|BUSY/CMD | 14 bit length(in octets)|
|
99 |
|
|
//
|
100 |
|
|
// 2 // MAC address (high) ??
|
101 |
|
|
// 3 // MAC address (low) ??
|
102 |
|
|
// 4 Number of receive packets missed (buffer was full)
|
103 |
|
|
// 5 Number of receive packets ending in error
|
104 |
|
|
// 6 Number of receive packets with invalid CRCs
|
105 |
|
|
// 7 (Number of transmit collisions ??)
|
106 |
|
|
//
|
107 |
|
|
// Creator: Dan Gisselquist, Ph.D.
|
108 |
|
|
// Gisselquist Technology, LLC
|
109 |
|
|
//
|
110 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
111 |
|
|
//
|
112 |
|
|
// Copyright (C) 2016, Gisselquist Technology, LLC
|
113 |
|
|
//
|
114 |
|
|
// This program is free software (firmware): you can redistribute it and/or
|
115 |
|
|
// modify it under the terms of the GNU General Public License as published
|
116 |
|
|
// by the Free Software Foundation, either version 3 of the License, or (at
|
117 |
|
|
// your option) any later version.
|
118 |
|
|
//
|
119 |
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
120 |
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
121 |
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
122 |
|
|
// for more details.
|
123 |
|
|
//
|
124 |
|
|
// You should have received a copy of the GNU General Public License along
|
125 |
|
|
// with this program. (It's in the $(ROOT)/doc directory, run make with no
|
126 |
|
|
// target there if the PDF file isn't present.) If not, see
|
127 |
|
|
// <http://www.gnu.org/licenses/> for a copy.
|
128 |
|
|
//
|
129 |
|
|
// License: GPL, v3, as defined and found on www.gnu.org,
|
130 |
|
|
// http://www.gnu.org/licenses/gpl.html
|
131 |
|
|
//
|
132 |
|
|
//
|
133 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
134 |
|
|
//
|
135 |
|
|
//
|
136 |
|
|
// `define RX_SYNCHRONOUS_WITH_WB_CLK
|
137 |
|
|
`ifdef RX_SYNCHRONOUS_WITH_WB_CLK
|
138 |
|
|
`define RXCLK i_wb_clk
|
139 |
|
|
`else
|
140 |
|
|
`define RXCLK i_net_rx_clk
|
141 |
|
|
`endif
|
142 |
|
|
// `define TX_SYNCHRONOUS_WITH_WB_CLK
|
143 |
|
|
`ifdef TX_SYNCHRONOUS_WITH_WB_CLK
|
144 |
|
|
`define TXCLK i_wb_clk
|
145 |
|
|
`else
|
146 |
|
|
`define TXCLK i_net_tx_clk
|
147 |
|
|
`endif
|
148 |
|
|
module enetpackets(i_wb_clk, i_reset,
|
149 |
50 |
dgisselq |
i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data, i_wb_sel,
|
150 |
30 |
dgisselq |
o_wb_ack, o_wb_stall, o_wb_data,
|
151 |
|
|
//
|
152 |
|
|
o_net_reset_n,
|
153 |
|
|
i_net_rx_clk, i_net_col, i_net_crs, i_net_dv, i_net_rxd, i_net_rxerr,
|
154 |
|
|
i_net_tx_clk, o_net_tx_en, o_net_txd,
|
155 |
|
|
//
|
156 |
|
|
o_rx_int, o_tx_int,
|
157 |
|
|
//
|
158 |
|
|
o_debug
|
159 |
|
|
);
|
160 |
|
|
parameter MEMORY_ADDRESS_WIDTH = 12; // Log_2 octet width:11..14
|
161 |
|
|
localparam MAW =((MEMORY_ADDRESS_WIDTH>14)? 14: // width of words
|
162 |
|
|
((MEMORY_ADDRESS_WIDTH<11)? 11:MEMORY_ADDRESS_WIDTH))-2;
|
163 |
|
|
input i_wb_clk, i_reset;
|
164 |
|
|
//
|
165 |
|
|
input i_wb_cyc, i_wb_stb, i_wb_we;
|
166 |
|
|
input [(MAW+1):0] i_wb_addr; // 1-bit for ctrl/data, 1 for tx/rx
|
167 |
|
|
input [31:0] i_wb_data;
|
168 |
50 |
dgisselq |
input [3:0] i_wb_sel;
|
169 |
30 |
dgisselq |
//
|
170 |
|
|
output reg o_wb_ack;
|
171 |
|
|
output wire o_wb_stall;
|
172 |
|
|
output reg [31:0] o_wb_data;
|
173 |
|
|
//
|
174 |
|
|
output reg o_net_reset_n;
|
175 |
|
|
//
|
176 |
|
|
input i_net_rx_clk, i_net_col, i_net_crs, i_net_dv;
|
177 |
|
|
input [3:0] i_net_rxd;
|
178 |
|
|
input i_net_rxerr;
|
179 |
|
|
//
|
180 |
|
|
input i_net_tx_clk;
|
181 |
|
|
output wire o_net_tx_en;
|
182 |
|
|
output wire [3:0] o_net_txd;
|
183 |
|
|
//
|
184 |
|
|
output wire o_rx_int, o_tx_int;
|
185 |
|
|
//
|
186 |
|
|
output wire [31:0] o_debug;
|
187 |
|
|
|
188 |
|
|
reg wr_ctrl;
|
189 |
|
|
reg [2:0] wr_addr;
|
190 |
|
|
reg [31:0] wr_data;
|
191 |
50 |
dgisselq |
reg [3:0] wr_sel;
|
192 |
30 |
dgisselq |
always @(posedge i_wb_clk)
|
193 |
|
|
begin
|
194 |
|
|
wr_ctrl<=((i_wb_stb)&&(i_wb_we)&&(i_wb_addr[(MAW+1):MAW] == 2'b00));
|
195 |
|
|
wr_addr <= i_wb_addr[2:0];
|
196 |
|
|
wr_data <= i_wb_data;
|
197 |
50 |
dgisselq |
wr_sel <= i_wb_sel;
|
198 |
30 |
dgisselq |
end
|
199 |
|
|
|
200 |
|
|
reg [31:0] txmem [0:((1<<MAW)-1)];
|
201 |
|
|
reg [31:0] rxmem [0:((1<<MAW)-1)];
|
202 |
|
|
|
203 |
|
|
reg [(MAW+1):0] tx_len;
|
204 |
|
|
|
205 |
|
|
`ifdef RX_SYNCHRONOUS_WITH_WB_CLK
|
206 |
49 |
dgisselq |
wire rx_broadcast;
|
207 |
30 |
dgisselq |
wire [(MAW+1):0] rx_len;
|
208 |
|
|
`else
|
209 |
49 |
dgisselq |
(* ASYNC_REG = "TRUE" *) reg rx_broadcast;
|
210 |
30 |
dgisselq |
(* ASYNC_REG = "TRUE" *) reg [(MAW+1):0] rx_len;
|
211 |
|
|
`endif
|
212 |
|
|
|
213 |
|
|
reg tx_cmd, tx_cancel;
|
214 |
|
|
`ifdef TX_SYNCHRONOUS_WITH_WB_CLK
|
215 |
|
|
wire tx_busy, tx_complete;
|
216 |
|
|
`else
|
217 |
|
|
reg tx_busy, tx_complete;
|
218 |
|
|
`endif
|
219 |
33 |
dgisselq |
reg config_hw_crc, config_hw_mac, config_hw_ip_check;
|
220 |
30 |
dgisselq |
reg rx_crcerr, rx_err, rx_miss, rx_clear;
|
221 |
|
|
`ifdef RX_SYNCHRONOUS_WITH_WB_CLK
|
222 |
|
|
wire rx_valid, rx_busy;
|
223 |
|
|
`else
|
224 |
|
|
reg rx_valid, rx_busy;
|
225 |
|
|
`endif
|
226 |
|
|
reg rx_wb_valid, pre_ack, pre_cmd, tx_nzero_cmd;
|
227 |
|
|
reg [4:0] caseaddr;
|
228 |
|
|
reg [31:0] rx_wb_data, tx_wb_data;
|
229 |
|
|
reg rx_err_stb, rx_miss_stb, rx_crc_stb;
|
230 |
|
|
|
231 |
|
|
reg [47:0] hw_mac;
|
232 |
|
|
reg p_rx_clear;
|
233 |
|
|
reg [7:0] clear_pipe;
|
234 |
|
|
|
235 |
|
|
initial config_hw_crc = 0;
|
236 |
|
|
initial config_hw_mac = 0;
|
237 |
33 |
dgisselq |
initial config_hw_ip_check = 0;
|
238 |
30 |
dgisselq |
initial o_net_reset_n = 1'b0;
|
239 |
|
|
initial tx_cmd = 1'b0;
|
240 |
|
|
initial tx_cancel = 1'b0;
|
241 |
|
|
initial rx_crcerr = 1'b0;
|
242 |
|
|
initial rx_err = 1'b0;
|
243 |
|
|
initial rx_miss = 1'b0;
|
244 |
|
|
initial rx_clear = 1'b0;
|
245 |
|
|
always @(posedge i_wb_clk)
|
246 |
|
|
begin
|
247 |
|
|
// if (i_wb_addr[(MAW+1):MAW] == 2'b10)
|
248 |
|
|
// Writes to rx memory not allowed here
|
249 |
50 |
dgisselq |
if ((i_wb_stb)&&(i_wb_we)&&(i_wb_addr[(MAW+1):MAW] == 2'b11)
|
250 |
|
|
&&(i_wb_sel[3]))
|
251 |
|
|
txmem[i_wb_addr[(MAW-1):0]][31:24] <= i_wb_data[31:24];
|
252 |
|
|
if ((i_wb_stb)&&(i_wb_we)&&(i_wb_addr[(MAW+1):MAW] == 2'b11)
|
253 |
|
|
&&(i_wb_sel[2]))
|
254 |
|
|
txmem[i_wb_addr[(MAW-1):0]][23:16] <= i_wb_data[23:16];
|
255 |
|
|
if ((i_wb_stb)&&(i_wb_we)&&(i_wb_addr[(MAW+1):MAW] == 2'b11)
|
256 |
|
|
&&(i_wb_sel[1]))
|
257 |
|
|
txmem[i_wb_addr[(MAW-1):0]][15:8] <= i_wb_data[15:8];
|
258 |
|
|
if ((i_wb_stb)&&(i_wb_we)&&(i_wb_addr[(MAW+1):MAW] == 2'b11)
|
259 |
|
|
&&(i_wb_sel[0]))
|
260 |
|
|
txmem[i_wb_addr[(MAW-1):0]][7:0] <= i_wb_data[7:0];
|
261 |
30 |
dgisselq |
|
262 |
|
|
// Set the err bits on these conditions (filled out below)
|
263 |
|
|
if (rx_err_stb)
|
264 |
|
|
rx_err <= 1'b1;
|
265 |
|
|
if (rx_miss_stb)
|
266 |
|
|
rx_miss <= 1'b1;
|
267 |
|
|
if (rx_crc_stb)
|
268 |
|
|
rx_crcerr <= 1'b1;
|
269 |
|
|
|
270 |
|
|
if ((wr_ctrl)&&(wr_addr==3'b000))
|
271 |
|
|
begin // RX command register
|
272 |
|
|
rx_crcerr<= (!wr_data[18])&&(!rx_crcerr);
|
273 |
|
|
rx_err <= (!wr_data[17])&&(!rx_err);
|
274 |
|
|
rx_miss <= (!wr_data[16])&&(!rx_miss);
|
275 |
|
|
// busy bit cannot be written to
|
276 |
|
|
rx_clear <= rx_clear || (wr_data[14]);
|
277 |
|
|
// Length bits are cleared when invalid
|
278 |
|
|
end else if (!rx_valid)
|
279 |
|
|
rx_clear <= 1'b0;
|
280 |
|
|
|
281 |
|
|
clear_pipe <= { clear_pipe[6:0], rx_clear };
|
282 |
|
|
p_rx_clear <= |clear_pipe;
|
283 |
|
|
|
284 |
|
|
if ((tx_busy)||(tx_cancel))
|
285 |
|
|
tx_cmd <= 1'b0;
|
286 |
|
|
if (!tx_busy)
|
287 |
|
|
tx_cancel <= 1'b0;
|
288 |
|
|
pre_cmd <= 1'b0;
|
289 |
|
|
if ((wr_ctrl)&&(wr_addr==3'b001))
|
290 |
|
|
begin // TX command register
|
291 |
|
|
|
292 |
|
|
// Reset bit must be held down to be valid
|
293 |
33 |
dgisselq |
config_hw_ip_check <= (!wr_data[18]);
|
294 |
30 |
dgisselq |
o_net_reset_n <= (!wr_data[17]);
|
295 |
|
|
config_hw_mac <= (!wr_data[16]);
|
296 |
|
|
config_hw_crc <= (!wr_data[15]);
|
297 |
|
|
pre_cmd <= (wr_data[14]);
|
298 |
|
|
tx_cancel <= (tx_busy)&&(!wr_data[14]);
|
299 |
|
|
// 14'h0 | SW-CRCn |NET-RST|BUSY/CMD | 14 bit length(in octets)|
|
300 |
|
|
tx_len <= wr_data[(MAW+1):0];
|
301 |
|
|
end
|
302 |
|
|
tx_nzero_cmd <= ((pre_cmd)&&(tx_len != 0));
|
303 |
|
|
if (tx_nzero_cmd)
|
304 |
|
|
tx_cmd <= 1'b1;
|
305 |
|
|
if (!o_net_reset_n)
|
306 |
|
|
tx_cancel <= 1'b1;
|
307 |
|
|
if (!o_net_reset_n)
|
308 |
|
|
tx_cmd <= 1'b0;
|
309 |
|
|
|
310 |
|
|
if ((wr_ctrl)&&(wr_addr==3'b010))
|
311 |
|
|
hw_mac[47:32] <= wr_data[15:0];
|
312 |
|
|
if ((wr_ctrl)&&(wr_addr==3'b011))
|
313 |
|
|
hw_mac[31:0] <= wr_data[31:0];
|
314 |
|
|
end
|
315 |
|
|
|
316 |
|
|
wire [31:0] w_tx_ctrl;
|
317 |
|
|
wire [31:0] w_rx_ctrl;
|
318 |
|
|
wire [3:0] w_maw;
|
319 |
|
|
|
320 |
|
|
assign w_maw = MAW+2; // Number of bits in the packet length field
|
321 |
49 |
dgisselq |
assign w_rx_ctrl = { 4'h0, w_maw, {(24-20){1'b0}},
|
322 |
|
|
(rx_valid)&&(rx_broadcast)&&(!rx_clear),
|
323 |
|
|
rx_crcerr, rx_err,
|
324 |
30 |
dgisselq |
rx_miss, rx_busy, (rx_valid)&&(!rx_clear),
|
325 |
|
|
{(14-MAW-2){1'b0}}, rx_len };
|
326 |
|
|
|
327 |
33 |
dgisselq |
assign w_tx_ctrl = { 4'h0, w_maw, {(24-19){1'b0}},
|
328 |
|
|
!config_hw_ip_check,
|
329 |
30 |
dgisselq |
!o_net_reset_n,!config_hw_mac,
|
330 |
|
|
!config_hw_crc, tx_busy,
|
331 |
|
|
{(14-MAW-2){1'b0}}, tx_len };
|
332 |
|
|
|
333 |
|
|
reg [31:0] counter_rx_miss, counter_rx_err, counter_rx_crc;
|
334 |
|
|
initial counter_rx_miss = 32'h00;
|
335 |
|
|
initial counter_rx_err = 32'h00;
|
336 |
|
|
initial counter_rx_crc = 32'h00;
|
337 |
|
|
|
338 |
|
|
// Reads from the bus ... always done, regardless of i_wb_we
|
339 |
|
|
always @(posedge i_wb_clk)
|
340 |
|
|
begin
|
341 |
|
|
rx_wb_data <= rxmem[i_wb_addr[(MAW-1):0]];
|
342 |
|
|
rx_wb_valid <= (i_wb_addr[(MAW-1):0] <= { rx_len[(MAW+1):2] });
|
343 |
|
|
tx_wb_data <= txmem[i_wb_addr[(MAW-1):0]];
|
344 |
|
|
pre_ack <= i_wb_stb;
|
345 |
|
|
caseaddr <= {i_wb_addr[(MAW+1):MAW], i_wb_addr[2:0] };
|
346 |
|
|
|
347 |
|
|
casez(caseaddr)
|
348 |
|
|
5'h00: o_wb_data <= w_rx_ctrl;
|
349 |
|
|
5'h01: o_wb_data <= w_tx_ctrl;
|
350 |
|
|
5'h02: o_wb_data <= {16'h00, hw_mac[47:32] };
|
351 |
|
|
5'h03: o_wb_data <= hw_mac[31:0];
|
352 |
|
|
5'h04: o_wb_data <= counter_rx_miss;
|
353 |
|
|
5'h05: o_wb_data <= counter_rx_err;
|
354 |
|
|
5'h06: o_wb_data <= counter_rx_crc;
|
355 |
|
|
5'h07: o_wb_data <= 32'h00;
|
356 |
|
|
5'b10???: o_wb_data <= (rx_wb_valid)?rx_wb_data:32'h00;
|
357 |
|
|
5'b11???: o_wb_data <= tx_wb_data;
|
358 |
|
|
default: o_wb_data <= 32'h00;
|
359 |
|
|
endcase
|
360 |
|
|
o_wb_ack <= pre_ack;
|
361 |
|
|
end
|
362 |
|
|
|
363 |
|
|
/////////////////////////////////////
|
364 |
|
|
//
|
365 |
|
|
//
|
366 |
|
|
//
|
367 |
|
|
// Transmitter code
|
368 |
|
|
//
|
369 |
|
|
//
|
370 |
|
|
//
|
371 |
|
|
/////////////////////////////////////
|
372 |
|
|
`ifdef TX_SYNCHRONOUS_WITH_WB_CLK
|
373 |
|
|
reg [(MAW+1):0] n_tx_len;
|
374 |
|
|
wire n_tx_cmd, n_tx_cancel;
|
375 |
|
|
assign n_tx_cmd = tx_cmd;
|
376 |
|
|
assign n_tx_cancel = tx_cancel;
|
377 |
|
|
`else
|
378 |
|
|
(* ASYNC_REG = "TRUE" *) reg [(MAW+1):0] n_tx_len;
|
379 |
|
|
(* ASYNC_REG = "TRUE" *) reg r_tx_cmd, r_tx_cancel;
|
380 |
|
|
reg n_tx_cmd, n_tx_cancel;
|
381 |
|
|
always @(posedge `TXCLK)
|
382 |
|
|
begin
|
383 |
|
|
r_tx_cmd <= tx_cmd;
|
384 |
|
|
r_tx_cancel <= tx_cancel;
|
385 |
|
|
|
386 |
|
|
n_tx_cmd <= r_tx_cmd;
|
387 |
|
|
n_tx_cancel <= r_tx_cancel;
|
388 |
|
|
end
|
389 |
|
|
`endif
|
390 |
|
|
|
391 |
|
|
`ifdef TX_SYNCHRONOUS_WITH_WB_CLK
|
392 |
|
|
reg last_tx_clk, tx_clk_stb;
|
393 |
|
|
(* ASYNC_REG = "TRUE" *) reg r_tx_clk;
|
394 |
|
|
always @(posedge i_wb_clk)
|
395 |
|
|
r_tx_clk <= i_net_tx_clk;
|
396 |
|
|
always @(posedge i_wb_clk)
|
397 |
|
|
last_tx_clk <= r_tx_clk;
|
398 |
|
|
always @(posedge i_wb_clk)
|
399 |
|
|
tx_clk_stb <= (r_tx_clk)&&(!last_tx_clk);
|
400 |
|
|
`else
|
401 |
|
|
wire tx_clk_stb, last_tx_clk;
|
402 |
|
|
|
403 |
|
|
assign tx_clk_stb = 1'b1;
|
404 |
|
|
assign last_tx_clk= 1'b0;
|
405 |
|
|
`endif
|
406 |
|
|
|
407 |
|
|
wire [(MAW+2):0] rd_tx_addr;
|
408 |
|
|
assign rd_tx_addr = (n_tx_addr+8);
|
409 |
|
|
|
410 |
|
|
reg [(MAW+2):0] n_tx_addr;
|
411 |
|
|
reg [31:0] n_tx_data, n_next_tx_data;
|
412 |
|
|
reg n_tx_complete;
|
413 |
|
|
`ifdef TX_SYNCHRONOUSH_WITH_WB
|
414 |
|
|
reg n_tx_busy, n_tx_config_hw_mac, n_tx_config_hw_crc;
|
415 |
|
|
`else
|
416 |
|
|
(* ASYNC_REG = "TRUE" *) reg n_tx_busy,
|
417 |
|
|
n_tx_config_hw_mac, n_tx_config_hw_crc;
|
418 |
|
|
`endif
|
419 |
|
|
(* ASYNC_REG = "TRUE" *) reg r_tx_crs;
|
420 |
|
|
reg n_tx_crs;
|
421 |
|
|
always @(posedge `TXCLK)
|
422 |
|
|
begin
|
423 |
|
|
r_tx_crs <= i_net_crs;
|
424 |
|
|
n_tx_crs <= r_tx_crs;
|
425 |
|
|
end
|
426 |
|
|
|
427 |
|
|
wire [31:0] n_remap_tx_data;
|
428 |
|
|
assign n_remap_tx_data[31:28] = n_next_tx_data[27:24];
|
429 |
|
|
assign n_remap_tx_data[27:24] = n_next_tx_data[31:28];
|
430 |
|
|
assign n_remap_tx_data[23:20] = n_next_tx_data[19:16];
|
431 |
|
|
assign n_remap_tx_data[19:16] = n_next_tx_data[23:20];
|
432 |
|
|
assign n_remap_tx_data[15:12] = n_next_tx_data[11: 8];
|
433 |
|
|
assign n_remap_tx_data[11: 8] = n_next_tx_data[15:12];
|
434 |
|
|
assign n_remap_tx_data[ 7: 4] = n_next_tx_data[ 3: 0];
|
435 |
|
|
assign n_remap_tx_data[ 3: 0] = n_next_tx_data[ 7: 4];
|
436 |
|
|
|
437 |
|
|
reg r_txd_en;
|
438 |
|
|
reg [3:0] r_txd;
|
439 |
|
|
initial r_txd_en = 1'b0;
|
440 |
|
|
|
441 |
|
|
initial n_tx_busy = 1'b0;
|
442 |
|
|
initial n_tx_complete = 1'b0;
|
443 |
|
|
always @(posedge `TXCLK)
|
444 |
|
|
begin
|
445 |
|
|
if (tx_clk_stb)
|
446 |
|
|
begin
|
447 |
|
|
// While this operation doesn't strictly need to
|
448 |
|
|
// operate *only* if tx_clk_stb is true, by doing so
|
449 |
|
|
// our code stays compatible with both synchronous
|
450 |
|
|
// to wishbone and synchronous to tx clk options.
|
451 |
|
|
n_next_tx_data <= txmem[(!n_tx_busy)?0:rd_tx_addr[(MAW+2):3]];
|
452 |
|
|
end
|
453 |
|
|
|
454 |
|
|
|
455 |
|
|
if (n_tx_cancel)
|
456 |
|
|
n_tx_busy <= 1'b0;
|
457 |
|
|
else if (!n_tx_busy)
|
458 |
|
|
n_tx_busy <= (n_tx_cmd)&&(!i_net_crs);
|
459 |
|
|
else if (n_tx_addr >= { n_tx_len,1'b0 })
|
460 |
|
|
n_tx_busy <= 1'b0;
|
461 |
|
|
|
462 |
|
|
if (!n_tx_busy)
|
463 |
|
|
begin
|
464 |
|
|
n_tx_addr <= {{(MAW+2){1'b0}},1'b1};
|
465 |
|
|
n_tx_data <= { n_remap_tx_data[27:0], 4'h0 };
|
466 |
|
|
if (n_tx_complete)
|
467 |
|
|
n_tx_complete <= (!n_tx_cmd);
|
468 |
|
|
r_txd_en <= (!n_tx_complete)&&(n_tx_cmd)&&(!i_net_crs);
|
469 |
|
|
r_txd <= n_remap_tx_data[31:28];
|
470 |
|
|
n_tx_config_hw_mac <= config_hw_mac;
|
471 |
|
|
n_tx_config_hw_crc <= config_hw_crc;
|
472 |
|
|
n_tx_len <= tx_len;
|
473 |
|
|
end else if (!r_txd_en)
|
474 |
|
|
r_txd_en <= (!n_tx_crs);
|
475 |
|
|
else if (tx_clk_stb) begin
|
476 |
|
|
n_tx_addr <= n_tx_addr + 1'b1;
|
477 |
|
|
r_txd <= n_tx_data[31:28];
|
478 |
|
|
if (n_tx_addr[2:0] == 3'h7)
|
479 |
|
|
n_tx_data <= n_remap_tx_data;
|
480 |
|
|
else
|
481 |
|
|
n_tx_data <= { n_tx_data[27:0], 4'h0 };
|
482 |
|
|
if (n_tx_addr >= { n_tx_len,1'b0 })
|
483 |
|
|
n_tx_complete <= 1'b1;
|
484 |
|
|
r_txd_en <= (n_tx_addr < { n_tx_len, 1'b0 });
|
485 |
|
|
end
|
486 |
|
|
end
|
487 |
|
|
|
488 |
|
|
wire n_tx_config_hw_preamble;
|
489 |
|
|
assign n_tx_config_hw_preamble = 1'b1;
|
490 |
|
|
|
491 |
|
|
wire w_macen, w_paden, w_txcrcen;
|
492 |
|
|
wire [3:0] w_macd, w_padd, w_txcrcd;
|
493 |
|
|
|
494 |
|
|
`ifndef TX_BYPASS_HW_MAC
|
495 |
|
|
addemac txmaci(`TXCLK, tx_clk_stb, n_tx_config_hw_mac, n_tx_cancel,
|
496 |
|
|
hw_mac, r_txd_en, r_txd, w_macen, w_macd);
|
497 |
|
|
`else
|
498 |
|
|
assign w_macen = r_txd_en;
|
499 |
|
|
assign w_macd = r_txd;
|
500 |
|
|
`endif
|
501 |
|
|
|
502 |
|
|
`ifndef TX_BYPASS_PADDING
|
503 |
|
|
addepad txpadi(`TXCLK, tx_clk_stb, 1'b1, n_tx_cancel,
|
504 |
|
|
w_macen, w_macd, w_paden, w_padd);
|
505 |
|
|
`else
|
506 |
|
|
assign w_paden = w_macen;
|
507 |
|
|
assign w_padd = w_macd;
|
508 |
|
|
`endif
|
509 |
|
|
|
510 |
|
|
`ifndef TX_BYPASS_HW_CRC
|
511 |
|
|
addecrc txcrci(`TXCLK, tx_clk_stb, n_tx_config_hw_crc, n_tx_cancel,
|
512 |
|
|
w_paden, w_padd, w_txcrcen, w_txcrcd);
|
513 |
|
|
`else
|
514 |
|
|
assign w_txcrcen = w_macen;
|
515 |
|
|
assign w_txcrcd = w_macd;
|
516 |
|
|
`endif
|
517 |
|
|
|
518 |
|
|
addepreamble txprei(`TXCLK, tx_clk_stb, n_tx_config_hw_preamble, n_tx_cancel,
|
519 |
|
|
w_txcrcen, w_txcrcd, o_net_tx_en, o_net_txd);
|
520 |
|
|
|
521 |
|
|
`ifdef TX_SYNCRONOUS_WITH_WB_CLK
|
522 |
|
|
assign tx_busy = n_tx_busy;
|
523 |
|
|
assign tx_complete = n_tx_complete;
|
524 |
|
|
`else
|
525 |
|
|
(* ASYNC_REG = "TRUE" *) reg r_tx_busy, r_tx_complete;
|
526 |
|
|
always @(posedge i_wb_clk)
|
527 |
|
|
begin
|
528 |
|
|
r_tx_busy <= (n_tx_busy || o_net_tx_en || w_txcrcen || w_macen || w_paden);
|
529 |
|
|
tx_busy <= r_tx_busy;
|
530 |
|
|
|
531 |
|
|
r_tx_complete <= n_tx_complete;
|
532 |
|
|
tx_busy <= r_tx_busy;
|
533 |
|
|
end
|
534 |
|
|
`endif
|
535 |
|
|
|
536 |
|
|
|
537 |
|
|
|
538 |
|
|
|
539 |
|
|
|
540 |
|
|
/////////////////////////////////////
|
541 |
|
|
//
|
542 |
|
|
//
|
543 |
|
|
//
|
544 |
|
|
// Receiver code
|
545 |
|
|
//
|
546 |
|
|
//
|
547 |
|
|
//
|
548 |
|
|
/////////////////////////////////////
|
549 |
|
|
`ifdef RX_SYNCHRONOUS_WITH_WB_CLK
|
550 |
|
|
reg last_rx_clk, rx_clk_stb;
|
551 |
|
|
(* ASYNC_REG="TRUE" *) reg r_rx_clk;
|
552 |
|
|
always @(posedge i_wb_clk)
|
553 |
|
|
r_rx_clk <= i_net_rx_clk;
|
554 |
|
|
always @(posedge i_wb_clk)
|
555 |
|
|
last_rx_clk <= r_rx_clk;
|
556 |
|
|
always @(posedge i_wb_clk)
|
557 |
|
|
rx_clk_stb <= (r_rx_clk)&&(!last_rx_clk);
|
558 |
|
|
|
559 |
|
|
`else
|
560 |
|
|
wire rx_clk_stb, last_rx_clk;
|
561 |
|
|
assign rx_clk_stb = 1'b1;
|
562 |
|
|
assign last_rx_clk = 1'b0;
|
563 |
|
|
`endif
|
564 |
|
|
|
565 |
|
|
|
566 |
|
|
`ifdef RX_SYNCHRONOUS_WITH_WB_CLK
|
567 |
|
|
wire n_rx_clear;
|
568 |
33 |
dgisselq |
reg n_rx_config_hw_mac, n_rx_config_hw_crc, n_rx_config_ip_check;
|
569 |
30 |
dgisselq |
assign n_rx_clear = rx_clear;
|
570 |
|
|
`else
|
571 |
33 |
dgisselq |
(* ASYNC_REG = "TRUE" *) reg n_rx_config_hw_mac, n_rx_config_hw_crc,
|
572 |
|
|
n_rx_config_ip_check;
|
573 |
30 |
dgisselq |
(* ASYNC_REG = "TRUE" *) reg r_rx_clear;
|
574 |
|
|
reg n_rx_clear;
|
575 |
|
|
always @(posedge `RXCLK)
|
576 |
|
|
begin
|
577 |
|
|
r_rx_clear <= (p_rx_clear)||(!o_net_reset_n);
|
578 |
|
|
n_rx_clear <= r_rx_clear;
|
579 |
|
|
end
|
580 |
|
|
`endif
|
581 |
|
|
|
582 |
|
|
|
583 |
|
|
reg n_rx_net_err;
|
584 |
33 |
dgisselq |
wire w_npre, w_rxmin, w_rxcrc, w_rxmac;
|
585 |
|
|
wire [3:0] w_npred, w_rxmind, w_rxcrcd, w_rxmacd;
|
586 |
30 |
dgisselq |
wire w_minerr, w_rxcrcerr, w_macerr, w_broadcast, w_iperr;
|
587 |
|
|
`ifndef RX_BYPASS_HW_PREAMBLE
|
588 |
|
|
rxepreambl rxprei(`RXCLK, rx_clk_stb, 1'b1, (n_rx_net_err),
|
589 |
|
|
i_net_dv, i_net_rxd, w_npre, w_npred);
|
590 |
|
|
`else
|
591 |
|
|
assign w_npre = i_net_dv;
|
592 |
|
|
assign w_npred = i_net_rxerr;
|
593 |
|
|
`endif
|
594 |
|
|
|
595 |
33 |
dgisselq |
`ifdef RX_BYPASS_HW_MINLENGTH
|
596 |
30 |
dgisselq |
// Insist on a minimum of 64-byte packets
|
597 |
33 |
dgisselq |
rxemin rxmini(`RXCLK, rx_clk_stb, 1'b1, (n_rx_net_err),
|
598 |
|
|
w_npre, w_npred, w_minerr);
|
599 |
30 |
dgisselq |
`else
|
600 |
33 |
dgisselq |
assign w_minerr= 1'b0;
|
601 |
|
|
`endif
|
602 |
30 |
dgisselq |
assign w_rxmin = w_npre;
|
603 |
|
|
assign w_rxmind= w_npred;
|
604 |
|
|
|
605 |
|
|
`ifndef RX_BYPASS_HW_CRC
|
606 |
|
|
rxecrc rxcrci(`RXCLK, rx_clk_stb, n_rx_config_hw_crc, (n_rx_net_err),
|
607 |
|
|
w_rxmin, w_rxmind, w_rxcrc, w_rxcrcd, w_rxcrcerr);
|
608 |
|
|
`else
|
609 |
|
|
assign w_rxcrc = w_rxmin;
|
610 |
|
|
assign w_rxcrcd = w_rxmind;
|
611 |
|
|
assign w_rxcrcerr= 1'b0;
|
612 |
|
|
`endif
|
613 |
|
|
|
614 |
|
|
`ifndef RX_BYPASS_HW_RMMAC
|
615 |
|
|
rxehwmac rxmaci(`RXCLK, rx_clk_stb, n_rx_config_hw_mac, (n_rx_net_err), hw_mac,
|
616 |
|
|
w_rxcrc, w_rxcrcd,
|
617 |
|
|
w_rxmac, w_rxmacd,
|
618 |
|
|
w_macerr, w_broadcast);
|
619 |
|
|
`else
|
620 |
|
|
assign w_rxmac = w_rxcrc;
|
621 |
|
|
assign w_rxmacd = w_rxcrcd;
|
622 |
|
|
`endif
|
623 |
|
|
|
624 |
33 |
dgisselq |
`define RX_HW_IPCHECK
|
625 |
30 |
dgisselq |
`ifdef RX_HW_IPCHECK
|
626 |
|
|
// Check: if this packet is an IP packet, is the IP header checksum
|
627 |
|
|
// valid?
|
628 |
33 |
dgisselq |
rxeipchk rxipci(`RXCLK, rx_clk_stb, n_rx_config_ip_check,(n_rx_net_err),
|
629 |
|
|
w_rxcrc, w_rxcrcd, w_iperr);
|
630 |
30 |
dgisselq |
`else
|
631 |
|
|
assign w_iperr = 1'b0;
|
632 |
|
|
`endif
|
633 |
|
|
|
634 |
|
|
wire w_rxwr;
|
635 |
|
|
wire [(MAW-1):0] w_rxaddr;
|
636 |
|
|
wire [31:0] w_rxdata;
|
637 |
|
|
wire [(MAW+1):0] w_rxlen;
|
638 |
|
|
|
639 |
33 |
dgisselq |
rxewrite #(MAW) rxememi(`RXCLK, 1'b1, (n_rx_net_err), w_rxmac, w_rxmacd,
|
640 |
30 |
dgisselq |
w_rxwr, w_rxaddr, w_rxdata, w_rxlen);
|
641 |
|
|
|
642 |
|
|
reg last_rxwr, n_rx_valid, n_rxmiss, n_eop, n_rx_busy, n_rx_crcerr,
|
643 |
|
|
n_rx_err, n_rx_broadcast, n_rx_miss;
|
644 |
|
|
reg [(MAW+1):0] n_rx_len;
|
645 |
|
|
|
646 |
|
|
initial n_rx_valid = 1'b0;
|
647 |
|
|
initial n_rx_clear = 1'b1;
|
648 |
|
|
initial n_rx_miss = 1'b0;
|
649 |
|
|
always @(posedge `RXCLK)
|
650 |
|
|
begin
|
651 |
|
|
if ((w_rxwr)&&(!n_rx_valid))
|
652 |
|
|
rxmem[w_rxaddr] <= w_rxdata;
|
653 |
|
|
|
654 |
|
|
// n_rx_net_err goes true as soon as an error is detected,
|
655 |
|
|
// and stays true as long as valid data is coming in
|
656 |
|
|
n_rx_net_err <= (i_net_dv)&&((i_net_rxerr)||(i_net_col)
|
657 |
|
|
||(w_minerr)||(w_macerr)||(w_rxcrcerr)
|
658 |
33 |
dgisselq |
||(w_iperr)
|
659 |
30 |
dgisselq |
||(n_rx_net_err)
|
660 |
|
|
||((w_rxwr)&&(n_rx_valid)));
|
661 |
|
|
|
662 |
|
|
last_rxwr <= w_rxwr;
|
663 |
|
|
n_eop <= (!w_rxwr)&&(last_rxwr)&&(!n_rx_net_err);
|
664 |
|
|
|
665 |
|
|
n_rx_busy <= (!n_rx_net_err)&&((i_net_dv)||(w_npre)||(w_rxmin)
|
666 |
33 |
dgisselq |
||(w_rxcrc)||(w_rxmac)||(w_rxwr));
|
667 |
30 |
dgisselq |
|
668 |
|
|
// Oops ... we missed a packet
|
669 |
|
|
n_rx_miss <= (n_rx_valid)&&(w_rxwr)||
|
670 |
|
|
((n_rx_miss)&&(!n_rx_clear));
|
671 |
|
|
|
672 |
|
|
n_rx_crcerr <= ((w_rxcrcerr)&&(!n_rx_net_err))
|
673 |
|
|
||((n_rx_crcerr)&&(!n_rx_clear));
|
674 |
|
|
|
675 |
|
|
n_rx_err <= ((n_rx_err)&&(!n_rx_clear))
|
676 |
|
|
||((i_net_rxerr)||(i_net_col)||(w_minerr));
|
677 |
|
|
|
678 |
|
|
n_rx_broadcast <= (w_broadcast)||((n_rx_broadcast)&&(!n_rx_clear));
|
679 |
|
|
|
680 |
|
|
if (n_rx_clear)
|
681 |
|
|
begin
|
682 |
|
|
n_rx_valid <= 1'b0;
|
683 |
|
|
n_rx_len <= 0;
|
684 |
|
|
end else if (n_eop)
|
685 |
|
|
begin
|
686 |
|
|
n_rx_valid <= 1'b1;
|
687 |
|
|
n_rx_len <= w_rxlen - ((n_rx_config_hw_crc)?{{(MAW-1){1'b0}},3'h4}:0);
|
688 |
|
|
end
|
689 |
|
|
// else n_rx_valid = n_rx_valid;
|
690 |
|
|
|
691 |
|
|
if ((!i_net_dv)||(n_rx_clear))
|
692 |
|
|
begin
|
693 |
33 |
dgisselq |
n_rx_config_hw_mac <= config_hw_mac;
|
694 |
|
|
n_rx_config_hw_crc <= config_hw_crc;
|
695 |
|
|
n_rx_config_ip_check <= config_hw_ip_check;
|
696 |
30 |
dgisselq |
end
|
697 |
|
|
end
|
698 |
|
|
|
699 |
|
|
`ifdef RX_SYNCHRONOUS_WITH_WB_CLK
|
700 |
|
|
assign rx_busy = n_rx_busy;
|
701 |
|
|
assign rx_valid = n_rx_valid;
|
702 |
|
|
assign rx_len = n_rx_len;
|
703 |
49 |
dgisselq |
assign rx_broadcast = n_rx_broadcast;
|
704 |
30 |
dgisselq |
`else
|
705 |
|
|
reg r_rx_busy, r_rx_valid;
|
706 |
|
|
always @(posedge i_wb_clk)
|
707 |
|
|
begin
|
708 |
|
|
r_rx_valid <= n_rx_valid;
|
709 |
|
|
rx_valid <= r_rx_valid;
|
710 |
|
|
|
711 |
|
|
r_rx_busy <= n_rx_busy;
|
712 |
|
|
rx_busy <= r_rx_busy;
|
713 |
|
|
|
714 |
|
|
rx_len <= n_rx_len;
|
715 |
49 |
dgisselq |
rx_broadcast <= n_rx_broadcast;
|
716 |
30 |
dgisselq |
end
|
717 |
|
|
|
718 |
|
|
`endif
|
719 |
|
|
|
720 |
|
|
reg [3:0] rx_err_pipe, rx_miss_pipe, rx_crc_pipe;
|
721 |
|
|
always @(posedge i_wb_clk)
|
722 |
|
|
begin
|
723 |
|
|
rx_err_pipe <= { rx_err_pipe[ 2:0],(n_rx_err)&&(rx_clk_stb) };
|
724 |
|
|
rx_miss_pipe <= { rx_miss_pipe[2:0],(n_rx_miss)&&(rx_clk_stb) };
|
725 |
|
|
rx_crc_pipe <= { rx_crc_pipe[ 2:0],(n_rx_crcerr)&&(rx_clk_stb) };
|
726 |
|
|
rx_err_stb <= (rx_err_pipe[ 3:2] == 2'b01);
|
727 |
|
|
rx_miss_stb <= (rx_miss_pipe[3:2] == 2'b01);
|
728 |
|
|
rx_crc_stb <= (rx_crc_pipe[ 3:2] == 2'b01);
|
729 |
|
|
end
|
730 |
|
|
|
731 |
|
|
always @(posedge i_wb_clk)
|
732 |
|
|
if (o_net_reset_n)
|
733 |
|
|
counter_rx_miss <= 32'h0;
|
734 |
|
|
else if (rx_miss_stb)
|
735 |
|
|
counter_rx_miss <= counter_rx_miss + 32'h1;
|
736 |
|
|
always @(posedge i_wb_clk)
|
737 |
|
|
if (o_net_reset_n)
|
738 |
|
|
counter_rx_err <= 32'h0;
|
739 |
|
|
else if (rx_err_stb)
|
740 |
|
|
counter_rx_err <= counter_rx_err + 32'h1;
|
741 |
|
|
always @(posedge i_wb_clk)
|
742 |
|
|
if (o_net_reset_n)
|
743 |
|
|
counter_rx_crc <= 32'h0;
|
744 |
|
|
else if (rx_crc_stb)
|
745 |
|
|
counter_rx_crc <= counter_rx_crc + 32'h1;
|
746 |
|
|
|
747 |
|
|
assign o_tx_int = !tx_busy;
|
748 |
|
|
assign o_rx_int = (rx_valid)&&(!rx_clear);
|
749 |
|
|
assign o_wb_stall = 1'b0;
|
750 |
|
|
|
751 |
|
|
wire [31:0] rxdbg;
|
752 |
|
|
wire rx_trigger; // reg rx_trigger;
|
753 |
|
|
/*
|
754 |
|
|
always @(posedge `RXCLK)
|
755 |
|
|
begin
|
756 |
|
|
if ((n_rx_clear)&&(!rx_trigger))
|
757 |
|
|
rx_trigger <= 1'b1;
|
758 |
|
|
else if (!n_rx_clear)
|
759 |
|
|
rx_trigger <= 1'b0;
|
760 |
|
|
end
|
761 |
|
|
*/
|
762 |
|
|
assign rx_trigger = i_net_dv;
|
763 |
|
|
|
764 |
|
|
assign rxdbg = { rx_trigger, n_eop, w_rxwr,
|
765 |
|
|
w_npre, w_npred,
|
766 |
|
|
w_rxcrc, w_rxcrcd,
|
767 |
|
|
w_macerr, w_broadcast, w_rxmac, w_rxmacd,
|
768 |
|
|
n_rx_clear, i_net_rxerr, n_rx_miss, n_rx_net_err,// 4 bits
|
769 |
|
|
n_rx_valid, n_rx_busy, i_net_crs, i_net_dv, // 4 bits
|
770 |
|
|
i_net_rxd }; // 4 bits
|
771 |
|
|
|
772 |
|
|
|
773 |
|
|
wire [31:0] txdbg;
|
774 |
|
|
assign txdbg = { n_tx_cmd, i_net_dv, rx_busy, n_rx_err, i_net_rxd,
|
775 |
|
|
{(24-(MAW+3)-10){1'b0}},
|
776 |
|
|
n_tx_addr[(MAW+2):0],
|
777 |
|
|
tx_clk_stb, n_tx_cancel,
|
778 |
|
|
n_tx_cmd, n_tx_complete, n_tx_busy, o_net_tx_en,
|
779 |
|
|
o_net_txd
|
780 |
|
|
};
|
781 |
|
|
|
782 |
|
|
assign o_debug = rxdbg;
|
783 |
|
|
endmodule
|