gateware

A collection of little open source FPGA hobby projects
git clone http://frotz.net/git/gateware.git
Log | Files | Refs | README

eth_rgmii_rx.sv (3263B)


      1 // Copyright 2020 Brian Swetland <swetland@frotz.net>
      2 // Licensed under the Apache License, Version 2.0.
      3 
      4 `default_nettype none
      5 
      6 module eth_rgmii_rx (
      7 	// 2.5MHz / 25MHz / 125MHz RGMII clock
      8 	input wire rx_clk,
      9 	
     10 	// RGMII input
     11 	input wire pin_rx_dv,
     12 	input wire [3:0]pin_rx_data,
     13 
     14 	// Packet byte data output
     15 	output reg [7:0] data = 0,
     16 
     17 	// Active when data is a valid byte
     18 	output reg valid = 0,
     19 
     20 	// Active for one rx_clk cycle when start of packet detected
     21 	// (start of preamble).  Typically 8 rx_clk's before the first
     22 	// valid data byte arrives.
     23 	output reg sop = 0,
     24 	
     25 	// Active for one rx_clk cycle when the packet has ended
     26 	// (*after) the last valid data byte arrives
     27 	output reg eop = 0,
     28 	
     29 	// Active when eop is active if packet FCS was valid
     30 	output reg crc_ok = 0
     31 );
     32 
     33 // NOTES:
     34 // 1. This is only functional for 1Gbe rates (125MHz clock) at present
     35 // 2. It considers any packet preamble consisting of one or more 0x55s
     36 //    and ending with an 0xD5 valid
     37 
     38 wire rx_dv;
     39 wire rx_err;
     40 wire [7:0]rx_data;
     41 
     42 // hardware-specific io buffers, delays, etc.
     43 eth_rgmii_rx_glue glue (
     44 	.rx_clk(rx_clk),
     45 	.pin_rx_dv(pin_rx_dv),
     46 	.pin_rx_data(pin_rx_data),
     47 	.rx_dv(rx_dv),
     48 	.rx_err(rx_err),
     49 	.rx_data(rx_data)
     50 );
     51 
     52 // RAWMODE disables all processing and blindly passes packet
     53 // data bytes though. sop will be active for the first byte
     54 // of the preamble and eop will become active for one cycle
     55 // after the last byte of the FCS. crc_ok will always be 0.
     56 // 
     57 // `define ETH_RGMII_RX_RAW_MODE
     58 
     59 `ifdef ETH_RGMII_RX_RAW_MODE
     60 reg next_sop;
     61 reg next_eop;
     62 reg next_valid;
     63 
     64 always_comb begin
     65 	next_sop = 0;
     66 	next_eop = 0;
     67 	next_valid = valid;
     68 
     69 	if (rx_dv) begin
     70 		if (~valid) begin
     71 			next_sop = 1;
     72 			next_valid = 1;
     73 		end
     74 	end else begin
     75 		if (valid) begin
     76 			next_eop = 1;
     77 			next_valid = 0;
     78 		end
     79 	end
     80 end
     81 
     82 always_ff @(posedge rx_clk) begin
     83 	sop <= next_sop;
     84 	eop <= next_eop;
     85 	data <= rx_data;
     86 	valid <= next_valid;
     87 end
     88 
     89 `else
     90 
     91 wire [31:0]crc;
     92 
     93 localparam IDLE = 2'd0;
     94 localparam PREAMBLE = 2'd1;
     95 localparam PACKET = 2'd2;
     96 localparam INVALID = 2'd3;
     97 
     98 reg [1:0]state = IDLE;
     99 reg [1:0]next_state;
    100 reg next_valid;
    101 reg [7:0]next_data;
    102 reg next_sop;
    103 reg next_eop;
    104 reg next_crc_ok;
    105 reg crc_en;
    106 
    107 always_comb begin
    108 	next_state = state;
    109 	next_data = data;
    110 	next_valid = 1'b0;
    111 	next_sop = 1'b0;
    112 	next_eop = 1'b0;
    113 	next_crc_ok = crc_ok;
    114 	crc_en = 1'b0;
    115 
    116 	case (state)
    117 	IDLE: if (rx_dv) begin
    118 		if (rx_data != 8'h55) begin
    119 			next_state = INVALID;
    120 		end else begin
    121 			next_state = PREAMBLE;
    122 			next_crc_ok = 1'b0;
    123 			next_sop = 1'b1;
    124 		end
    125 	end
    126 	PREAMBLE: begin // .. 55 55 55 D5 
    127 		if (rx_data == 8'hD5) begin
    128 			next_state = PACKET;
    129 		end else if (rx_data != 8'h55) begin
    130 			next_state = INVALID;
    131 		end
    132 	end
    133 	PACKET: begin
    134 		if (rx_dv == 1'b1) begin
    135 			crc_en = 1'b1;
    136 			next_data = rx_data;
    137 			next_valid = 1'b1;
    138 		end else begin
    139 			next_crc_ok = (crc == 32'hDEBB20E3);
    140 			next_eop = 1'b1;
    141 			next_state = IDLE;
    142 		end
    143 	end
    144 	INVALID: if (rx_dv == 1'b0) begin
    145 		next_state = IDLE;
    146 	end
    147 	endcase
    148 end
    149 
    150 always_ff @(posedge rx_clk) begin
    151 	state <= next_state;
    152 	data <= next_data;
    153 	valid <= next_valid;
    154 	sop <= next_sop;
    155 	eop <= next_eop;
    156 	crc_ok <= next_crc_ok;
    157 end
    158 
    159 eth_crc32_8 crc32(
    160 	.clk(rx_clk),
    161 	.en(crc_en),
    162 	.rst(sop),
    163 	.din(rx_data),
    164 	.crc(crc)
    165 );
    166 `endif
    167 
    168 endmodule