gateware

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

eth_rmii_rx.sv (4136B)


      1 // Copyright 2014 Brian Swetland <swetland@frotz.net>
      2 // Licensed under the Apache License, Version 2.0.
      3 
      4 `timescale 1ns / 1ps
      5 
      6 // CRS_DV -- multiplexed, CR on first di-bit, DV on second di-bit of each nibble
      7 //
      8 //           preamble | packet 
      9 // crs_dv ... 1 1 1 1 1 CR DV CR DV CR DV CR ...
     10 // rx0    ... 0 0 0 0 1 b0 b2 b4 b6 b0 b2 b4 ...
     11 // rx1    ... 1 1 1 1 1 b1 b3 b5 b7 b1 b3 b5 ...
     12 //
     13 // CR can go low when carrier lost, while DV remains asserted through end of frame.
     14 
     15 // valid is asserted on each clock where data contains a byte of the frame
     16 // eop is asserted for one clock after the last byte of the frame has arrived
     17 // and before the next frame's first byte arrives
     18 
     19 module eth_rmii_rx(
     20 	// 50MHz RMII clock
     21 	input clk50,
     22 
     23 	// RMII input
     24 	input [1:0]rx,
     25 	input crs_dv,
     26 
     27 	// packet byte data output
     28 	output reg [7:0]data = 0,
     29 
     30 	// active when data is a valid byte (once every 4 clk50s during rx)
     31 	output reg valid = 0,
     32 
     33 	// active for a single clk50 before the first byte of a packet arrives
     34 	output reg sop = 0,
     35 
     36 	// active for a single clk50 after the last byte has arrived
     37 	output reg eop = 0,
     38 	
     39 	// active as of eop and until sop, if packet crc32 is valid
     40 	output reg crc_ok = 0,
     41 
     42 	// transmit outputs which can drive
     43 	// an eth_rmii_tx to create a repeater
     44 	output reg [1:0]out_tx = 0,
     45 	output reg out_txen = 0
     46 	);
     47 
     48 localparam IDLE = 4'd0;
     49 localparam PRE1 = 4'd1;
     50 localparam PRE2 = 4'd2;
     51 localparam PRE3 = 4'd3;
     52 localparam DAT0 = 4'd4;
     53 localparam DAT1 = 4'd5;
     54 localparam DAT2 = 4'd6;
     55 localparam DAT3 = 4'd7;
     56 localparam ERR0 = 4'd8;
     57 localparam ERR1 = 4'd9;
     58 localparam EOP = 4'd10;
     59 
     60 reg [3:0]state = IDLE;
     61 reg [3:0]next_state;
     62 
     63 reg [7:0]next_data;
     64 reg next_valid;
     65 reg next_eop;
     66 
     67 wire [7:0]rxshift = { rx, data[7:2] };
     68 
     69 reg [1:0]delay_tx = 0;
     70 reg delay_txen = 0;
     71 reg next_txen;
     72 reg next_sop;
     73 reg next_crc_ok;
     74 
     75 wire [31:0]crc;
     76 reg crc_en;
     77 
     78 eth_crc32_2 rx_crc(
     79 	.clk(clk50),
     80 	.en(crc_en),
     81 	.rst(sop),
     82 	.din(rx),
     83 	.crc(crc)
     84 );
     85 
     86 always_comb begin
     87 	next_state = state;
     88 	next_data = data;
     89 	next_valid = 0;
     90 	next_eop = 0;
     91 	next_sop = 0;
     92 	next_txen = delay_txen;
     93 	next_crc_ok = crc_ok;
     94 	crc_en = 0;
     95 
     96 	if (sop) begin
     97 		// always mark crc invalid at start of packet
     98 		next_crc_ok = 0;
     99 	end else if (valid) begin
    100 		// record crc validity after each byte is received
    101 		// if we just leave it free-running, we end up shifting in
    102 		// bogus data from after the FCS but before we observe DV
    103 		// deasserting mid-byte
    104 		next_crc_ok = (crc == 32'hdebb20e3);
    105 	end
    106 
    107 	case (state)
    108 	IDLE: if ((rx == 2'b01) && (crs_dv == 1)) begin
    109 		// crs_dv may go high asynchronously
    110 		// only move to preamble on crs_dv AND a preamble di-bit
    111 		next_state = PRE1;
    112 		next_txen = 1;
    113 		next_sop = 1;
    114 	end
    115 	PRE1: if (rx == 2'b01) begin
    116 		next_state = PRE2;
    117 	end else begin
    118 		next_state = ERR0;
    119 	end
    120 	PRE2: if (rx == 2'b01) begin
    121 		next_state = PRE3;
    122 	end else begin
    123 		next_state = ERR0;
    124 	end
    125 	PRE3: if (rx == 2'b11) begin
    126 		next_state = DAT0;
    127 	end else if (rx == 2'b01) begin
    128 		next_state = PRE3;
    129 	end else begin
    130 		next_state = ERR0;
    131 	end
    132 	DAT0: begin
    133 		next_data = rxshift;
    134 		crc_en = 1'b1;
    135 		next_state = DAT1;
    136 	end
    137 	DAT1: begin
    138 		next_data = rxshift;
    139 		crc_en = 1'b1;
    140 		if (crs_dv) begin
    141 			next_state = DAT2;
    142 		end else begin
    143 			next_txen = 0;
    144 			next_state = EOP;
    145 		end
    146 	end
    147 	DAT2: begin
    148 		next_data = rxshift;
    149 		crc_en = 1'b1;
    150 		next_state = DAT3;
    151 	end
    152 	DAT3: begin
    153 		next_data = rxshift;
    154 		crc_en = 1'b1;
    155 		if (crs_dv) begin
    156 			next_state = DAT0;
    157 			next_valid = 1;
    158 		end else begin
    159 			next_txen = 0;
    160 			next_state = EOP;
    161 		end
    162 	end
    163 	EOP: begin
    164 		next_state = IDLE;
    165 		next_data = 0;
    166 		next_eop = 1;
    167 	end
    168 	ERR0: begin
    169 		next_txen = 0;
    170 		if (crs_dv == 0) begin
    171 			next_state = ERR1;
    172 		end
    173 	end
    174 	ERR1: begin
    175 		if (crs_dv == 0) begin
    176 			next_state = IDLE;
    177 		end else begin
    178 			next_state = ERR0;
    179 		end
    180 	end
    181 	default: begin
    182 		next_state = IDLE;
    183 	end
    184 	endcase
    185 end
    186 
    187 always_ff @(posedge clk50) begin
    188 	state <= next_state;
    189 	valid <= next_valid;
    190 	data <= next_data;
    191 	eop <= next_eop;
    192 	sop <= next_sop;
    193 	delay_txen <= next_txen;
    194 	delay_tx <= rx;
    195 	out_txen <= next_txen ? delay_txen : 0;
    196 	out_tx <= next_txen ? delay_tx : 0;
    197 	crc_ok <= next_crc_ok;
    198 end
    199 
    200 endmodule