aboutsummaryrefslogtreecommitdiffstats
path: root/eth/rtl/verilog/MAC_rx/MAC_rx_FF.v
blob: e212b8986c076dabd70d73d4620a768b0a8fdbf7 (plain)
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?