// //////////////////////////////////////////////////////////////////// // 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?