1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
// ////////////////////////////////////////////////////////////////////
// Completely Rewritten by M. Ettus, no John Gao code left
// ////////////////////////////////////////////////////////////////////
module MAC_rx_FF
#(parameter RX_FF_DEPTH = 9)
(input Reset,
input Clk_MAC,
input Clk_SYS,
// MAC_rx_ctrl interface
input [7:0] Fifo_data,
input Fifo_data_en,
output Fifo_full,
input Fifo_data_err,
input Fifo_data_end,
output [15:0] Fifo_space,
// CPU
input RX_APPEND_CRC,
input [4:0] Rx_Hwmark,
input [4:0] Rx_Lwmark,
// User interface
output Rx_mac_empty,
input Rx_mac_rd,
output [31:0] Rx_mac_data,
output [1:0] Rx_mac_BE,
output Rx_mac_sop,
output Rx_mac_eop,
output Rx_mac_err,
// FIFO Levels
output [15:0] fifo_occupied,
output fifo_full_dbg,
output fifo_empty
);
reg [1:0] FF_state;
reg [2:0] PKT_state;
reg [31:0] staging;
reg [35:0] staging2;
reg line_ready, line_ready_d1;
wire sop_i, eop_i;
reg [1:0] be;
always @(posedge Clk_MAC or posedge Reset)
if(Reset)
FF_state <= 0;
else
if(Fifo_data_err | Fifo_data_end)
FF_state <= 0;
else if(Fifo_data_en)
FF_state <= FF_state + 1;
always @(posedge Clk_MAC or posedge Reset)
if(Reset)
staging[31:0] <= 0;
else if(Fifo_data_en)
case(FF_state)
0 : staging[31:24] <= Fifo_data;
1 : staging[23:16] <= Fifo_data;
2 : staging[15:8] <= Fifo_data;
3 : staging[7:0] <= Fifo_data;
endcase // case(FF_state)
localparam PKT_idle = 0;
localparam PKT_sop = 1;
localparam PKT_pkt = 2;
localparam PKT_end = 3;
localparam PKT_err = 4;
always @(posedge Clk_MAC or posedge Reset)
if(Reset)
PKT_state <= 0;
else
case(PKT_state)
PKT_idle :
if(Fifo_data_en)
PKT_state <= PKT_sop;
PKT_sop, PKT_pkt :
if(Fifo_data_err | (line_ready & Fifo_full))
PKT_state <= PKT_err;
else if(Fifo_data_end)
PKT_state <= PKT_end;
else if(line_ready & ~Fifo_full)
PKT_state <= PKT_pkt;
PKT_end :
PKT_state <= PKT_idle;
PKT_err :
if(~Fifo_full)
PKT_state <= PKT_idle;
endcase // case(PKT_state)
assign sop_i = (PKT_state == PKT_sop);
assign eop_i = (PKT_state == PKT_end);
always @(posedge Clk_MAC)
if(line_ready)
staging2 <= {sop_i, eop_i, be[1:0], staging};
always @(posedge Clk_MAC)
if(Reset)
line_ready <= 0;
else if((Fifo_data_en & (FF_state==2'd3)) | Fifo_data_end | Fifo_data_err)
line_ready <= 1;
else
line_ready <= 0;
always @(posedge Clk_MAC)
line_ready_d1 <= line_ready;
always @(posedge Clk_MAC)
if(Fifo_data_end | Fifo_data_err)
be <= FF_state;
else
be <= 0;
wire sop_o, eop_o, empty;
wire [1:0] be_o;
wire [RX_FF_DEPTH-1:0] occupied, occupied_sysclk;
wire [31:0] dataout;
/*
fifo_2clock #(.DWIDTH(36),.AWIDTH(RX_FF_DEPTH)) mac_rx_fifo
(.wclk(Clk_MAC),.datain((PKT_state==PKT_err) ? 36'hF_FFFF_FFFF : staging2),.write(~Fifo_full & (line_ready_d1|(PKT_state==PKT_err))),
.full(Fifo_full),.level_wclk(occupied),
.rclk(Clk_SYS),.dataout({sop_o,eop_o,be_o[1:0],dataout}),.read(Rx_mac_rd),
.empty(empty),.level_rclk(),
.arst(Reset) );
*/
fifo_xlnx_2Kx36_2clk mac_rx_ff_core
(
.din((PKT_state==PKT_err) ? 36'hF_FFFF_FFFF : staging2), // Bus [35 : 0]
.rd_clk(Clk_SYS),
.rd_en(Rx_mac_rd),
.rst(Reset),
.wr_clk(Clk_MAC),
.wr_en(~Fifo_full & (line_ready_d1|(PKT_state==PKT_err))),
.dout({sop_o,eop_o,be_o[1:0],dataout}), // Bus [35 : 0]
.empty(empty),
.full(Fifo_full),
.rd_data_count(occupied_sysclk), // Bus [11 : 0]
.wr_data_count(occupied)); // Bus [11 : 0]
assign Fifo_space[15:RX_FF_DEPTH] = 0;
assign Fifo_space[RX_FF_DEPTH-1:0] = ~occupied;
assign fifo_occupied = occupied_sysclk;
assign fifo_full_dbg = Fifo_full; // FIXME -- in wrong clock domain
assign fifo_empty = empty;
// mac side fifo interface
// Input - Rx_mac_rd
// Output - Rx_mac_empty, Rx_mac_sop, Rx_mac_eop, Rx_mac_err, Rx_mac_data, Rx_mac_BE
assign Rx_mac_BE = be_o;
assign Rx_mac_sop = sop_o & ~eop_o;
assign Rx_mac_eop = eop_o;
assign Rx_mac_err = sop_o & eop_o;
assign Rx_mac_empty = empty;
assign Rx_mac_data = dataout;
endmodule // MAC_rx_FF
// FIXME Should we send out an "almost full" signal instead of full?
|